内部排序算法比较

一、题目描述

通过随机数据比较各排序算法的关键字比较次数和关键字移动次数,以 及执行时间,取得直观感受。

二、设计要求

一、需求分析

实现各排序算法,分别进行以下各组比较,并进行总结。

一、各算法在不同规模下的比较。

1)比较范围:直接插入排序、冒泡法排序、简单选择排序、快速排序1(自己实现)、快速排序2(调用STL)、归并排序。

2)比较指标:a)关键字操作次数(比较次数和移动次数之和),b)排序时间。每个指标采用多次重复取平均数记录,重复次数不小于100。注:1次关键字对换按3次移动计算。

3)数据规模:分别为50,100,500,1000,5000,10000;

4)数据类型:随机数据

二、算法在不同数据类型下的比较

1)比较范围:直接插入排序、冒泡法排序、简单选择排序、快速排序1(自己实现)、快速排序2(调用STL)、归并排序。

2)比较指标:a)关键字操作次数(比较次数和移动次数之和),b)排序时间。每个指标采用多次重复取平均数记录,重复次数不小于100。注:1次关键字对换按3次移动计算。

3)数据规模:10000;

4)数据类型:随机数据、正序数据、逆序数据;

三、代码要求

1、必须要有异常处理,比如删除空链表时需要抛出异常;

2、保持良好的编程的风格:

代码段与段之间要有空行和缩近

标识符名称应该与其代表的意义一致

函数名之前应该添加注释说明该函数的功能 、关键代码应说明其功能

3、递归程序注意调用的过程,防止栈溢出

四、算法分析

#include<iostream>
#include<time.h>
#include <algorithm>
#include<stdlib.h>
#include <windows.h>
#include <string>
using namespace std;

//关键次数初始化
static long long move1=0;
static long long move2=0;
static long long move3=0;
static long long move4=0;
static long long move5=0;
static long long move6=0;

//输出结果
void print(int a[], int n){
        for(int j= 0; j<n; j++){
            cout<<a[j] <<"  ";
        }
        cout<<endl<<endl;
    }  

/***********归并排序*******************/
 void Merge(int r[],int rf[], int i, int m, int n)   //归并操作
{
    int j,k;
    for(j=m+1,k=i; i<=m && j <=n ; ++k){
        move1+=1;
        if(r[i] < r[j]) {rf[k] = r[i++]; move1+=3; move1+=1;}
        else {rf[k] = r[j++]; move1+=3; move1+=1;}
    }  

    while(i <= m)  {rf[k++] = r[i++];  move1+=3; move1+=2;}
    move1+=1;
    while(j <= n)  {rf[k++] = r[j++];  move1+=3; move1+=2;}
    move1+=1;

 }  

void MSort(int r[], int rf[], int s, int t)   //将r[]归并排序为rf[]
{
        move1+=1;
        //int *rf2=new int[t];
        int rf2[10000+1];
        if(s==t) {rf[s] = r[s];  move1+=3;}
        else
        {
            move1+=1;
            int m=(s+t)/2;              /*平分*p 表*/
            MSort(r, rf2, s, m);        /*递归地将p[s…m]归并为有序的p2[s…m]*/
            MSort(r, rf2, m+1, t);      /*递归地将p[m+1…t]归并为有序的p2[m+1…t]*/
            Merge(rf2, rf, s, m,t);   /*将p2[s…m]和p2[m+1…t]归并到p1[s…t]*/

        }  

 }  

void MergeSort(int r[], int rf[], int n)
{   /*对顺序表*p 作归并排序*/ 

        MSort(r, rf, 0, n-1);
 }
/*************归并排序结束*******************/

/***********快速排序1(递归)*******************/
/*
void swap(int* a,int*b)
{
    int temp;
    temp=*a;
    *a=*b;
    *b=temp;
    move2+=3;
}
int Partition(int a[],int low,int high)
{
    int pivotkey= a[low];
    while(low<high)
    {
        while (low<high&&a[high]>=pivotkey) { --high;move2+=1;}
        swap(&a[low],&a[high]);
        while (low<high&&a[low<=pivotkey]){ ++low;move2+=1;}
        swap(&a[low],&a[high]);
    }
    move2+=1
     return low;
}
void quickSort(int a[], int low, int high)
{
    int pivotloc;
    if (low<high)
    {
        pivotloc = Partition(a,low,high);    //将表一分为二
        quickSort(a,low,pivotloc-1);        //递归对低子表递归排序
        quickSort(a,pivotloc+1,high);      //递归对高子表递归排序
    }
    move2+=1;
}*/

/*************快速排序1(递归)结束*******************/

/***********快速排序1(非递归)*******************/

void quicksort(int a[],int n)
{
            struct node
            {
                int low,high;
            }st[10000];
           int i,j,low,high,temp,top=0;
           st[top].low=0;
           st[top].high=n-1;
           while(top>-1)
           {   low=st[top].low;
               high=st[top].high;
               top--;
               i=low;
               j=high;
               if(low<high)
               {
                   move2+=1;
                   temp=a[low];
                   while(i!=j)
                   {
                       move2+=1;
                       while(i<j&&a[j]>temp){   j--;  move2+=1;}
                       if(i<j){a[i]=a[j];i++;move2+=3;}
                       while(i<j&&a[i]<temp){  i++;   move2+=1;}
                       if(i<j){a[j]=a[i];j--;move2+=3;}
                   }
                   a[i]=temp;  

                   top++;
                   st[top].low=low;
                   st[top].high=i-1;  

                   top++;
                   st[top].low=i+1;
                   st[top].high=high;
               }
               move2+=1;
           }
           move2+=1;
    }
/*************快速排序1(非递归)结束*******************/

/*************冒泡排序开始*******************/
void bubbleSort(int a[], int n)
{
    int temp;
    for(int i=0;i<n-1;i++)
        for(int j=0;j<n-i-1;j++)
        {
            if(a[j]>a[j+1])
            {
                temp=a[j];
                a[j]=a[j+1];
                a[j+1]=temp;
                move3+=3;
            }
            move3+=1;
        }
}
/*************冒泡排序结束*******************/

/*************简单选择排序开始*******************/
void selectSort(int a[], int n)
{
    int key,temp;
    for(int i=1;i<n;i++)
    {
        key=i-1;
        for(int j=i;j<n;j++)
        {
            if(a[j]<a[key])
            {
                key=j;
                move4+=3;
            }
            move4+=1;
        }
        if(key!=i-1)
        {
            temp=a[key];
            a[key]=a[i-1];
            a[i-1]=temp;
            move4+=3;
        }
        move4+=1;
        //  print(a,n,i);           //打印每趟排序的结果
    }
}
/*************简单选择排序结束*******************/

/*************直接插入排序结束*******************/
void InsertSort(int a[], int n)
{
        for(int i= 1; i<n; i++){
            if(a[i] < a[i-1]){               //若第i个元素大于i-1元素,直接插入。小于的话,移动有序表后插入
                move5+=1;
                int j= i-2;
                int x = a[i];        //复制为哨兵,即存储待排序元素
                move5+=3;
                a[i] = a[i-1];           //先后移一个元素
                move5+=1;
                while(x < a[j]&&j>=0){  //查找在有序表的插入位置
                    a[j+1] = a[j];
                    j--;         //元素后移
                    move5+=1;
                }
                move5+=1;
                a[j+1] = x;      //插入到正确位置
            }
            move5+=1;
           // print(a,n,i);           //打印每趟排序的结果
        }
}
/*************直接插入排序结束*******************/

/*************STL快速排序开始************************/
int comp(const void*a,const void*b)
{
    move6+=3;
    return *(int*)a-*(int*)b;
}
/*************STL快速排序结束************************/

//汇总所有的排序算法
void sort123(int z,int type)
{
        /********初始化变量*********************/
        //clock_t *start=new clock_t[100];
        //clock_t *end=new clock_t[100];
        long long *start=new long long[100];
        long long *end=new long long[100];
        double *dfMinus=new double[100];
        double *dfTim=new double[100];
        LARGE_INTEGER litmp;
        double  dfFreq;
        QueryPerformanceFrequency(& litmp);         //获取CPU时钟频率
        dfFreq = (double)litmp.QuadPart;
        double times1=0;
        double times2=0;
        double times3=0;
        double times4=0;
        double times5=0;
        double times6=0;
        srand(time(NULL));
        //给原数组赋值
        for(int i=0;i<=99;i++)
        {
            //初始化各个数组
            int *a=new int[z];
            int *c=new int[z];
            int *d=new int[z];
            int *e=new int[z];
            int *f=new int[z];
            int *g=new int[z];
            if(type==0)
            {
                for(int j=0;j<z;j++)   //下标法
                {
                    a[j]=rand();

                    c[j]=a[j];
                    d[j]=a[j];
                    e[j]=a[j];
                    f[j]=a[j];
                    g[j]=a[j];
                }
            }
            else if(type==1)
            {
                for( int j=0;j<z;j++)
                {
                    a[j]=j+i;

                    c[j]=a[j];
                    d[j]=a[j];
                    e[j]=a[j];
                    f[j]=a[j];
                    g[j]=a[j];
                }
            }
            else
            {
                for(int j=0;j<z;j++)
                {
                    a[j]=z-j+i;

                    c[j]=a[j];
                    d[j]=a[j];
                    e[j]=a[j];
                    f[j]=a[j];
                    g[j]=a[j];
                }
            }

                /***归并排序开始*******/
                QueryPerformanceCounter(&litmp);         //获取开始计数值
                start[i] = litmp.QuadPart;
                int *b=new int[z];   //b数组用于归并排序
                MergeSort(c,b, z);
                QueryPerformanceCounter(&litmp);        //获取结束计数值
                end[i] = litmp.QuadPart;
                dfMinus[i] = (double)(end[i]- start[i]);
                dfTim[i] = dfMinus[i]/dfFreq;                       //计算持续时间,单位为秒误差不超过1微妙算持续时间,单位为秒误差不超过1微妙
                times1+=dfTim[i];
                delete []b;
                delete []c;
                /*****归并排序结束********/

                /***快速排序1开始*******/
                QueryPerformanceCounter(&litmp);         //获取开始计数值
                start[i] = litmp.QuadPart;
                quicksort(d,z); //此处用的是非递归快排,非递归需要堆栈不是很大
                //quickSort(d,0,z-1);   //此处是递归快排算法,算法在上面已经注释掉,因为快排递归需要堆栈太大,一般电脑需要调整堆栈,我改动的为5032768字节(随便,够大就好)
                QueryPerformanceCounter(&litmp);        //获取结束计数值
                end[i] = litmp.QuadPart;
                dfMinus[i] = (double)(end[i]- start[i]);
                dfTim[i] = dfMinus[i]/dfFreq;                       //计算持续时间,单位为秒误差不超过1微妙算持续时间,单位为秒误差不超过1微妙
                times2+=dfTim[i];
                //if(i<=0)
                //  print(d,z);
                delete []d;
                /*****快速排序1结束********/

                /***冒泡开始*******/
                QueryPerformanceCounter(&litmp);         //获取开始计数值
                start[i] = litmp.QuadPart;
                bubbleSort(e,z);           //冒泡排序
                QueryPerformanceCounter(&litmp);        //获取结束计数值
                end[i] = litmp.QuadPart;
                dfMinus[i] = (double)(end[i]- start[i]);
                dfTim[i] = dfMinus[i]/dfFreq;                       //计算持续时间,单位为秒误差不超过1微妙算持续时间,单位为秒误差不超过1微妙
                times3+=dfTim[i];
                delete []e;
                /*****冒泡结束********/

                /***选择法开始*******/
                QueryPerformanceCounter(&litmp);         //获取开始计数值
                start[i] = litmp.QuadPart;
                selectSort(f,z);       //简单选择排序
                QueryPerformanceCounter(&litmp);        //获取结束计数值
                end[i] = litmp.QuadPart;
                dfMinus[i] = (double)(end[i]- start[i]);
                dfTim[i] = dfMinus[i]/dfFreq;                       //计算持续时间,单位为秒误差不超过1微妙算持续时间,单位为秒误差不超过1微妙
                times4+=dfTim[i];
                delete []f;
                /*****选择法结束********/

                /***插入法开始*******/
                QueryPerformanceCounter(&litmp);         //获取开始计数值
                start[i] = litmp.QuadPart;
                InsertSort(g,z);         //直接插入排序
                QueryPerformanceCounter(&litmp);        //获取结束计数值
                end[i] = litmp.QuadPart;
                dfMinus[i] = (double)(end[i]- start[i]);
                dfTim[i] = dfMinus[i]/dfFreq;                       //计算持续时间,单位为秒误差不超过1微妙算持续时间,单位为秒误差不超过1微妙
                times5+=dfTim[i];
                delete []g;
                /*****插入法结束********/

                /***STL快排法开始*******/
                QueryPerformanceCounter(&litmp);         //获取开始计数值
                start[i] = litmp.QuadPart;
                //sort(a, a+z);         //STL一种改进型分段算法
                qsort(a,z,sizeof(int),comp);
                QueryPerformanceCounter(&litmp);        //获取结束计数值
                end[i] = litmp.QuadPart;
                dfMinus[i] = (double)(end[i]- start[i]);
                dfTim[i] = dfMinus[i]/dfFreq;                       //计算持续时间,单位为秒误差不超过1微妙算持续时间,单位为秒误差不超过1微妙
                times6+=dfTim[i];
                /*****STL快排法结束********/

                delete []a;
        }
                delete []start;
                delete []end;
                delete []dfMinus;
                delete []dfTim;
        /***********打印用时**********************/
        string s;
        if(type==0)  {  s="随机数据";cout<<s<<endl;}
        else if(type==1)  {  s="正序数据";cout<<s<<endl;}
        else   {  s="逆序数据";cout<<s<<endl;}

        cout<<"归并排序:          "<<z<<"个"<<s<<"重复实验100次;"<<" 关键字操作次数平均为"<<move1/100<<"次"<<endl<<"平均耗时"<<times1/100*1000<<"   毫秒"<<endl<<endl;
        cout<<"快速排序(非递归):  "<<z<<"个"<<s<<"重复实验100次;"<<" 关键字操作次数平均为"<<move2/100<<"次"<<endl<<"平均耗时"<<times2/100*1000<<"   毫秒"<<endl<<endl;
        cout<<"冒泡排序:          "<<z<<"个"<<s<<"重复实验100次;"<<" 关键字操作次数平均为"<<move3/100<<"次"<<endl<<"平均耗时"<<times3/100*1000<<"   毫秒"<<endl<<endl;
        cout<<"简单选择排序:      "<<z<<"个"<<s<<"重复实验100次;"<<" 关键字操作次数平均为"<<move4/100<<"次"<<endl<<"平均耗时"<<times4/100*1000<<"   毫秒"<<endl<<endl;
        cout<<"直接插入排序:      "<<z<<"个"<<s<<"重复实验100次;"<<" 关键字操作次数平均为"<<move5/100<<"次"<<endl<<"平均耗时"<<times5/100*1000<<"   毫秒"<<endl<<endl;
        cout<<"STL快速排序:       "<<z<<"个"<<s<<"重复实验100次;"<<" 关键字操作次数平均为"<<move6/100<<"次"<<endl<<"平均耗时"<<times6/100*1000<<"   毫秒"<<endl<<endl;

}

//主函数
int main()
{
        sort123(50,0);
        sort123(100,0);
        sort123(500,0);
        sort123(1000,0);
        sort123(5000,0);
        sort123(10000,0);
        sort123(10000,1);
        sort123(10000,2);
        system("pause");
        return 0;
 }  

六、结果截图

七、结果分析:

1、随机数据比较:数据规模分别为50,100,500,1000,5000,10000,我们经过验证可以得出初步结论:

在数据基本无序的状态下且数据较多:排序效率比较如下:

快速排序法>STL快速排序法>归并排序法>直接插入排序法>简单选择法>

冒泡排序法

在数据基本无序的状态下且数据较少:排序效率比较如下:

快速排序法>STL快速排序法>直接插入排序法简单选择法>冒泡排序法>

归并排序法

在数据更少的情况下,直接插入法也有奇效。

2、正序数据比较:数据规模为10000,我们经过验证可以得出初步结论:

在数据基本有序且为正序的状态下:排序效率如下:

直接插入排序>STL快速排序法>归并排序>快速排序>简单选择排序>

冒泡排序法

3、逆序数据比较:数据规模为10000,我们经过验证可以得出初步结论:

在数据基本有序且为正序的状态下:排序效率如下:

STL快速排序法>归并排序>快速排序>直接插入排序>简单选择排序>

冒泡排序法

八、总结

1、涉及递归的有归并排序以及快速排序,这两个都是我编写程序的时候感觉最艰难的。

2、归并排序使用的数组除了中间要合并用的那个rf2用的是静态数组,其他都是动态数组new创建的,堆创建数组本来是挺好的,可是这里却因为数据规模较大的时候,递归太深rf2又无法delete[],只能用数组,创建了一个rf2[10001].

3、快速排序我写了两种方法,一种是递归的,一种是非递归的,递归真的理解是最简单的,可是对堆栈真的要求太高了,递归本来是崩溃的,不过忽然找到了方法:因为快排递归需要堆栈太大,一般电脑需要调整堆栈,我改动的为5032768字节(随便,够大就好)

4、时间精度的问题也好解决,用的是QueryPerformance,这个精度非常好,学到的好东西。

时间: 2024-11-08 00:39:27

内部排序算法比较的相关文章

数据结构6种内部排序算法的比较

1.需求分析 (1)输入数据的形式为:伪随机数产生程序产生,且每次输入数不少于100个,至少要用5组不同的输入数据 (2)输出的形式为:输出关键字参加的比较次数和关键字的移动次数(关键字交换计为3次移动)的数据 (3)程序能达到的功能:对起泡排序,直接插入排序,简单选择排序,快速排序,希尔排序,堆排序这6种常用的内部排序算法进行比较,比较的指标为有关键字参加的比较次数和关键字的移动次数(关键字交换计为3次移动) (4)测试数据:正确输入为由伪随机数产生程序产生100个随机数,然后输出比较结果,错

内部排序算法(一):交换排序(冒泡排序,快速排序)

这是我的博文系列<内部排序算法>的第一篇.所谓排序,就是要整理文件中的记录,使之按关键字递增(或递减)次序排列起来.所谓内部排序,是指在排序过程中,若整个文件都是放在内存中处理,排序时不涉及数据的内.外存交换(外排序的定义则相反). 内部排序法按照策略可以划分为五类:插入排序.选择排序.交换排序.归并排序和分配排序.待排文件的存储方式采用顺序表(或直接用向量)作为存储结构(其他的存储结构还有以链表作为存储结构等). 在这个系列的博文中,我按照排序算法的给出,排序算法的分析(包括算法的时空复杂度

八大内部排序算法(上)-冒泡、直接插入、简单选择、快速

八大内部排序算法(上)冒泡.直接插入.简单选择.快速 排序分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存. 我们这里说说八大排序就是内部排序. 1.直接插入排序 将一个记录插入到已排序好的有序表中,从而得到一个新,记录数增1的有序表.即:先将序列的第1个记录看成是一个有序的子序列,然后从第2个记录逐个进行插入,直至整个序列有序为止. 要点:设立哨兵,作为临时存储和判断数组边界之用. 直接插入实现如下:

Java实现各种内部排序算法

数据结构中常见的内部排序算法: 插入排序:直接插入排序.折半插入排序.希尔排序 交换排序:冒泡排序.快速排序 选择排序:简单选择排序.堆排序 归并排序.基数排序.计数排序 直接插入排序: 思想:每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子序列中,直到全部记录插入完成. 性能:时间复杂度:最好o(n):有序,最坏o(n^2):逆序,平均o(n^2):空间复杂度o(1):稳定 1 public int[] straightInsertSort(int array[]){ 2 int

七大内部排序算法总结(插入排序、希尔排序、冒泡排序、简单选择排序、快速排序、归并排序、堆排序)

 写在前面: 排序是计算机程序设计中的一种重要操作,它的功能是将一个数据元素的任意序列,重新排列成一个按关键字有序的序列.因此排序掌握各种排序算法非常重要.对下面介绍的各个排序,我们假定所有排序的关键字都是整数.对传入函数的参数默认是已经检查好了的.只是简单的描述各个算法并给出了具体实现代码,并未做其他深究探讨. 基础知识: 由于待排序的记录数量不同,使得排序过程中设计的存储器不同,可将排序方法分为两大类:一类是内部排序,指的是待排序记录存放在计算机随机存储器中进行的排序过程.另一类是外部排序,

内部排序算法小结

内部排序算法主要分为插入类排序.交换类排序和选择类排序,它们在性能上的差异主要体现在时间复杂度.空间复杂度和稳定性.各种排序算法都会进行元素间的比较和移动,时间复杂度主要由整个排序过程中的比较次数和移动次数决定.空间复杂度体现在除了待排序记录本身所占的空间,排序过程中占用了多少辅助空间. 1.插入类排序 直接插入排序 如果待排序记录之间是顺序排列,此时整个排序过程中元素比较的次数为n-1次,移动次数为0次.如果待排序记录之间是逆序排列,第i趟排序比较次数为i,移动的次数为i+1,其中i的范围是2

内部排序算法的稳定性

1.排序 排序是计算机程序设计中的一个重要操作,因此学习和研究各种排序算法是一个重要的课题. 2.排序种类 根据排序记录的数量和排序过程中的存储器不同,可以将排序分为内部排序和外部排序. 内部排序:指的是将带排序记录存放到计算机内存中进行排序的过程. 外部排序:指的是带排序的记录数量很大,以至于内存一次不能容纳全部记录,在排序过程中尚需对外存进行访问的排序过程. 3.排序稳定性 关于排序的稳定性:如果排序前2个相等的数在序列的前后位置顺序和排序后它们两个的前后位置顺序相同,就是稳定的排序,否则就

王道数据结构内部排序算法总结

首先看一下内部排序分类以及各个算法的时间复杂度.空间复杂度和稳定性 一.插入排序 1.直接插入排序 (Straight Insertion Sort)的基本思想是:把n个待排序的元素看成为一个有序表和一个无序表.开始时有序表中只包含1个元素,无序表中包含有n-1个元素,排序过程中每次从无序表中取出第一个元素,将它插入到有序表中的适当位置,使之成为新的有序表,重复n-1次可完成排序过程. 代码: 方法一: void InsertSort(ElemType A[],int n) { int i,j;

排序---内部排序算法(快排、希尔排序、归并排序、基数排序、冒泡、选择排序)比较

1.内部排序的复杂度总结 1)时间复杂度 4种排序的平均时间复杂度是O(nlog2n),"快些以nlog2n的速度归队"(快排.希尔排序.归并.堆排序) 最坏情况下,快排的时间复杂度为O(n*n) 2)空间复杂度 O(log2n)快排 O(n)归并 O(rd)基数 其他都是O(1) 3)稳定性 不稳定的:"考研复习痛苦啊,情绪不稳定,快些选一堆好友来聊天吧"(快排.希尔.简单选择排序.堆排序) 其他都是稳定的. 4)一趟排序,保证一个关键字到达最终位置 交换类(起泡