8种内部排序算法比较 (C++)

8种内部排序算法比较 (C++)

内容

对大量整数或单词排序,分别用内部排序算法-插入排序(1.直接插入排序、2.折半插入排序、3.希尔排序)、交换排序(4.冒泡、5.快速排序)、选择排序(6.直接选择排序、7.堆排序)和归并排序(8.2-路归并排序)具体实现 ,并可计算排序时间,验证时间复杂度。

实验方法

输入实验次数 n n n 和实验数据量 m m m,程序分 n n n 次,每次产生8个相同的长度为 m m m 的随机整数数组,使用上述8种算法进行排序,分别记录运行时长。全部完成后,输出时长列表和平均时长。

源代码

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>
#undef OVERFLOW
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
#define N 8         //函数数量
#define SHOWRESULT 0//显示排序结果
typedef int Keytype;
typedef struct{
    Keytype key;
}ElemType;
typedef struct{     //线性顺序表(0号单元不用)
    ElemType* r;    //存储空间基址
    int length;     //当前长度
    int listsize;   //当前分配的存储容量,以sizeof(ElemType)为单位
}SqList;
void InitList(SqList* L,int num,int size);//初始化数据
void Operate(SqList* L,clock_t** time,int num,void (**fun)(SqList&),int times);//排序
void Output(SqList* L,int num,clock_t** time,char** name,int times);
void DestroyList(SqList* L,int num);
int LT(Keytype key1,Keytype key2);//判断小于
void InsertSort(SqList &L);//直接插入排序
void BInsertSort(SqList &L);//折半插入
void ShellSort(SqList &L);//希尔排序
void ShellInsert(SqList &L,int dk);//对一个增量值,完成一轮排序
void Delta(SqList L,int* &delta,int &deltalength);//生成希尔排序的增量数组,采用Hibbard增量序列
void BubbleSort(SqList &L);//冒泡排序
int midindex(SqList L,int low,int high);//中值下标
int Paritition(SqList &L,int low,int high);//对线性表的一部分,确定枢轴和其前后的元素集合
void QSort(SqList &L,int low,int high);//对线性表从low到high的子列采用快排
void QuickSort(SqList &L);//快速排序接口
void SelectSort(SqList &L);//直接选择排序
void HeapSort(SqList &L);//堆排序
void HeapAdjust(SqList &L,int low,int high);//已知以low为堆顶的堆,除堆顶以外均满足堆,调整堆,使之成为大顶堆
void Merge(ElemType* r,ElemType* temp,int n1,int n2,int n3);//将相邻有序的L[n1..n2..n3]归并为有序的T[n1..n3]
void MSort(ElemType* r,ElemType* temp,int low,int high);//将子列归并排序,从r的子列归并到t的子列
void MergeSort(SqList &L);//归并排序接口
/*
对大量整数或单词排序,分别用内部排序算法-插入排序(1.直接插入排序、2.折半插入排序、3.希尔排序)、交换排序(4.冒泡、5.快速排序)、选择排序(6.直接选择排序、7.堆排序)和归并排序(8.2-路归并排序)具体实现 ,并可计算排序时间,验证时间复杂度。
*/
int main()
{
    SqList L[N];
    clock_t* time[N];
    int i,n,m;
    void (*fun[N])(SqList&)={InsertSort,BInsertSort,ShellSort,BubbleSort,QuickSort,SelectSort,HeapSort,MergeSort};
    char* name[N]={(char*)"直接插入排序",(char*)"折半插入排序",(char*)"希尔排序",(char*)"冒泡排序",(char*)"快速排序",(char*)"直接选择排序",(char*)"堆排序",(char*)"2-路归并排序"};
    printf("[不同的排序方法对比]\n");
    printf("请分别输入 实验次数 和 实验数据量 : ");
    scanf("%d%d",&n,&m);
    if(n>0&&m>0){//可运行
        for(i=0;i<=N-1;i++) if(!(time[i]=(clock_t*)calloc(n,sizeof(clock_t)))) exit(OVERFLOW);
        for(i=0;i<=n-1;i++){
            InitList(L,N,m);
            Operate(L,time,N,fun,i);
            DestroyList(L,N);
        }
        Output(L,N,time,name,n);
    }
    system("pause");
}
void InitList(SqList* L,int num,int size)//初始化数据
{
    int i,j;
    for(i=0;i<=num-1;i++){
        L[i].length=size;
        if(!(L[i].r=(ElemType*)calloc(L[i].length+1,sizeof(ElemType)))) exit(OVERFLOW);
    }
    srand((unsigned)time(NULL));
    for(i=1;i<=L[0].length;i++) L[0].r[i].key=rand();
    for(i=1;i<=num-1;i++){//复制数据
        L[i].length=L[0].length;
        for(j=1;j<=L[0].length;j++) L[i].r[j]=L[0].r[j];
    }
}
void Operate(SqList* L,clock_t** time,int num,void (**fun)(SqList&),int times)//排序
{
    clock_t start,end;
    int i;
    for(i=0;i<=num-1;i++){
        start=clock();
        fun[i](L[i]);
        end=clock();
        time[i][times]=end-start;
    }
}
void Output(SqList* L,int num,clock_t** time,char** name,int times)
{
    int i,j;
    double average[num];
    for(i=0;i<=num-1;i++){//输出每一种算法的时长列表
        printf("%-15s ",name[i]);
        #if(SHOWRESULT==OK)
            printf("结果: ");
            for(j=1;j<=L[i].length;j++) printf("%d ",L[i].r[j].key);
        #endif
        printf("耗时:\t");
        for(j=0;j<=times-1;j++) printf("%d ms\t",time[i][j]);
        putchar('\n');
    }
    printf("\n平均时长\n");
    for(i=0;i<=num-1;i++){//计算并输出平均时长列表
        average[i]=0;
        for(j=0;j<=times-1;j++) average[i]+=time[i][j];
        average[i]/=times;
        printf("%-15s: %g ms\n",name[i],average[i]);
    }
}
void DestroyList(SqList* L,int num)
{
    for(num-=1;num>=0;num--){
        L[num].length=0;
        free(L[num].r);
    }
}
int LT(Keytype key1,Keytype key2)//判断序
{
    if(key1<key2) return TRUE;
    return FALSE;
}
void InsertSort(SqList &L)//直接插入排序
{
    int i,j;
    for(i=2;i<=L.length;i++){
        if(LT(L.r[i].key,L.r[i-1].key)){
            L.r[0]=L.r[i];
            L.r[i]=L.r[i-1];
            for(j=i-2;j>=1&&LT(L.r[0].key,L.r[j].key);j--){
                L.r[j+1]=L.r[j];
            }
            L.r[j+1]=L.r[0];
        }
    }
}
void BInsertSort(SqList &L)//折半插入
{
    int i,j,mid,low,high;
    for(i=2;i<=L.length;i++){
        if(LT(L.r[i].key,L.r[i-1].key)){//需要移动
            L.r[0]=L.r[i];
            for(low=1,high=i-1,mid=(low+high)/2;low<=high;){
                if(LT(L.r[0].key,L.r[mid].key)) high=mid-1;
                else low=mid+1;
                mid=(low+high)/2;
            }//插入在low+1位置
            for(j=i-1;j>=high+1;j--) L.r[j+1]=L.r[j];
            L.r[high+1]=L.r[0];
        }
    }
}
void ShellInsert(SqList &L,int dk)//对一个增量值,完成一轮排序
{
    int i,j;
    for(i=dk+1;i<=L.length;i++){
        if(LT(L.r[i].key,L.r[i-dk].key)){
            L.r[0]=L.r[i];
            for(j=i-dk;j>0&&LT(L.r[0].key,L.r[j].key);j-=dk){
                L.r[j+dk]=L.r[j];
            }
            L.r[j+dk]=L.r[0];
        }
    }
}
void ShellSort(SqList &L)//希尔排序
{
    int i,*delta,deltalength;
    Delta(L,delta,deltalength);
    for(i=0;i<=deltalength-1;i++) ShellInsert(L,delta[i]);
    free(delta);
}
void Delta(SqList L,int* &delta,int &deltalength)//生成希尔排序的增量数组,采用Hibbard增量序列
//采用Hibbard 增量序列,通项d_i=2^i-1,i=1,2,...,[log[2](length)]=deltalength
//此序列倒序填充到delta数组中,i=0,1,2,...,[log[2](length)-1]=deltalength-1
{
    int i;
    deltalength=log2(L.length);
    if(!(delta=(int*)calloc(deltalength,sizeof(int)))) exit(OVERFLOW);
    delta[deltalength-1]=1;
    for(i=2;deltalength-i>=0;i++) delta[deltalength-i]=2*delta[deltalength-i+1]+1;
}
void BubbleSort(SqList &L)//冒泡排序
{
    int i,j,k,change;
    for(i=L.length,change=TRUE;i>=2&&change;i--){
        change=FALSE;
        for(j=1;j<=i-1;j++){
            if(LT(L.r[j+1].key,L.r[j].key)){
                change=TRUE;
                L.r[0]=L.r[j];
                L.r[j]=L.r[j+1];
                L.r[j+1]=L.r[0];
            }
        }
    }
}
int Paritition(SqList &L,int low,int high)//对线性表的一部分,确定枢轴和其前后的元素集合
{
    int i;
    i=midindex(L,low,high);     //三中值优化
    L.r[0]=L.r[i];            //枢轴寄存到0处
    if(i!=low) L.r[i]=L.r[low]; //low与i(枢轴)交换
    while(low<high){            //起始时,low即为枢轴下标
        while(low<high&&!LT(L.r[high].key,L.r[0].key)) high--;
        L.r[low]=L.r[high];     //结束时,high为枢轴下标
        while(low<high&&!LT(L.r[0].key,L.r[low].key)) low++;
        L.r[high]=L.r[low];     //结束时,low为枢轴下标
    }
    L.r[low]=L.r[0];
    return low;
}
int midindex(SqList L,int low,int high)//中值下标
{
    if(high<low+2) return low;
    int mid=(low+high)/2,o1,o2,o3;
    o1=LT(L.r[low].key,L.r[mid].key);
    o2=LT(L.r[mid].key,L.r[high].key);
    if((o1&&o2)||(!o1&&!o2)) return mid;
    o3=LT(L.r[low].key,L.r[high].key);
    if((!o1&&o3)||(o1&&!o3)) return low;
    return high;
}
void QSort(SqList &L,int low,int high)//对线性表从low到high的子列采用快排
{
    int pivotloc;
    if(low<high){
        pivotloc=Paritition(L,low,high);//确定枢轴位置,移动元素
        QSort(L,low,pivotloc-1);
        QSort(L,pivotloc+1,high);
    }
}
void QuickSort(SqList &L)//快速排序接口
{
    QSort(L,1,L.length);
}
void SelectSort(SqList &L)//直接选择排序
{
    int i,j,minindex;
    for(i=1;i<L.length;i++){//最后一个不需要排
        for(j=minindex=i;j<=L.length;j++) if(LT(L.r[j].key,L.r[minindex].key)) minindex=j;//找出从i开始的最小项
        if(i!=minindex){
            L.r[0]=L.r[i];
            L.r[i]=L.r[minindex];
            L.r[minindex]=L.r[0];
        }
    }
}
void HeapSort(SqList &L)//堆排序
{
    int i;
    for(i=L.length/2;i>0;i--) HeapAdjust(L,i,L.length);//建立大顶堆
    for(i=L.length;i>1;i--){//确定第i号元素
        L.r[0]=L.r[1];
        L.r[1]=L.r[i];
        L.r[i]=L.r[0];
        HeapAdjust(L,1,i-1);
    }
}
void HeapAdjust(SqList &L,int low,int high)//已知以low为堆顶的堆,除堆顶以外均满足堆,调整堆,使之成为大顶堆
{
    int i;
    L.r[0]=L.r[low];//暂存堆顶元素
    for(i=2*low;i<=high;i*=2){
        if(i<high&&LT(L.r[i].key,L.r[i+1].key)) i++;//取兄弟里最大的
        if(!LT(L.r[0].key,L.r[i].key)) break;//找到了放置位置
        L.r[low]=L.r[i];
        low=i;      //将更大的上移一层,low更改
    }
    L.r[low]=L.r[0];//放置原先的堆顶元素
}
void Merge(ElemType* r,ElemType* temp,int n1,int n2,int n3)//将相邻有序的[n1..n2],[n2+1..n3]归并为有序的[n1..n3]
{
    int i,j,k;
    for(k=i=n1,j=n2+1;i<=n2&&j<=n3;k++){
        if(LT(r[i].key,r[j].key)){
            temp[k]=r[i];
            i++;
        }
        else{
            temp[k]=r[j];
            j++;
        }
    }//k结束时位于被归并的子列后一个位置
    if(i<=n2) for(;i<=n2;k++,i++) temp[k]=r[i];
    if(j<=n3) for(;j<=n3;j++,k++) temp[k]=r[j];
    for(i=n1;i<=n3;i++) r[i]=temp[i];
}
void MSort(ElemType* r,ElemType* temp,int low,int high)//将子列归并排序,从r的子列归并到t的子列
{
    int mid=(low+high)/2;
    if(low>=high) return;
    MSort(r,temp,low,mid);
    MSort(r,temp,mid+1,high);
    Merge(r,temp,low,mid,high);
}
void MergeSort(SqList &L)//归并排序接口
{
    ElemType *temp; //临时数列
    if(!(temp=(ElemType*)calloc(L.length+1,sizeof(ElemType)))) exit(OVERFLOW);
    MSort(L.r,temp,1,L.length);
    free(temp);
}

运行结果

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

  • 3
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值