四种排序算法性能比较实验

这是中科大2021年春季课程《算法分析与设计》的课程实验1

实验题目

实验题目

结果+唠嗑

由于实验要求,本次实验采用的四种排序算法分别是:插入O(n2),归并O(nlg(n)),堆排序O(nlg(n)),以及喜闻乐见的快速排序O(nlg(n))。考虑到设计运行时间的比较,所以采用了快且稳定的C语言。(其实我真的没的选,除了C只会python)
所有数据都是随机乱序生成的,都说快排是系数相对小的nlgn算法,实验结果真的如此吗?先上结果图:
品军时间和方差
方差为什么波动这么大我也不知道,非常不幸的是插入排序如果放进图里,其他三条曲线全部都得趴在地上,别说抬头了,连个波动都不会有。这就是来自数量级的时间压制。
运行数据我都附在后面的exel文档里,其实我对每个运行结果都进行了截图,不过由于我的程序没怎么考虑输出的交互,所以有些丑,我就不贴了。数据处理用的也是这个exel软件。感兴趣的可以下载查看,链接我之后贴在评论区吧,私信我也可以。

排序的原理我也不说了,值得一提的是这个时间的统计方式,我调用了C的系统库time.h,利用了其中的计时工具来记录每一次排序所消耗的时间,然后我就可以直接一次运行10组记录数据嘿嘿。是不是方便了很多呢,其实并没有,4种排序算法,每个10组,每个跑10次,400个数据对我来说其实统计维护也挺麻烦的,出于结果考虑,有的情况明显可能是CPU调度之类的其他莫名其妙原因产生了比较大的系统偏差,我就进行了第二、三次重跑。

基本可以确定,对于随机生成的无序数组,在数据量相对比较大的时候(5万-50万范围)排序所有元素运行时间,有

归并>堆>快排

代码

好啦,主要也就是这个结论啦,代码双手奉上:

#include <time.h>
#include <stdio.h>
#include <stdlib.h> 

#define MAXINT 2147483647
#define ARRAY 300000
		//生成多大的数组
#define RANGE 10000000
		//产生随机数的最大值

void BuildArray (long *p,long size){
	long i; 
    srand((unsigned) time(NULL)); //用时间做种,每次产生随机数不一样
//	printf("size=%d\t",size); 
    for (i = 0; i < size; i ++){
        p[i] = (rand()*32767+rand()) % RANGE + 1;  //产生1-RANGE的随机数
//        printf("%ld ",p[i]); 
    }
}

void swap(long *a, long *b){
    int temp;
    temp = *a;
    *a = *b;
    *b = temp;
}

void InsertionSort(long *arr, long size){
    long i, j, tmp;
    for (i = 1; i < size; i++) {
        if (arr[i] < arr[i-1]) {
            tmp = arr[i];
            for (j = i - 1; j >= 0 && arr[j] > tmp; j--) {
                arr[j+1] = arr[j];
            }
            arr[j+1] = tmp;
        }
    }
}

void Heapify(long *arr,long m,long size){
    long i, tmp;
    tmp = arr[m];
    for (i = 2 * m; i <= size; i *= 2) {
        if (i + 1 <= size && arr[i] < arr[i+1]) {
            i++;
        }
        if (arr[i] < tmp) {
            break;
        }
        arr[m] = arr[i];
        m = i;
    }
    arr[m] = tmp;
}

void Merge(long *num,long start,long mid, int end){
    long *temp = (long *)malloc((end-start+1) * sizeof(long));    //申请空间来存放两个有序区归并后的临时区域
    long i = start;
    long j = mid + 1;
    long k = 0;

    while (i <= mid && j <= end){
        if (num[i] <= num[j]){
            temp[k++] = num[i++];
        } else {
            temp[k++] = num[j++];
        }
    }

    while (i <= mid){
        temp[k++] = num[i++];
    }
    while (j <= end){
        temp[k++] = num[j++];
    } 

    //将临时区域中排序后的元素,整合到原数组中
    for (i = 0; i < k; i++){
        num[start + i] = temp[i];
    }

    free(temp);
}

void MergeSort(long *num, long start,long end){
    long mid = start + (end - start) / 2;

    if (start >= end){
        return;
    }
    
    MergeSort(num, start, mid);
    MergeSort(num, mid + 1, end);

    Merge(num, start, mid, end);
}

void BuildHeap(long  A[],long i,long N){
    long child;
    long Tmp=A[i];

    for ( ; 2*i+1 < N; i = child){
        child = 2*i+1; 				//左孩子是2*i+1
        if (child != N - 1 && A[child + 1] > A[child])
            child++;                //找到较大的儿子节点与父亲比较 
        if (Tmp < A[child])
            A[i] = A[child];
        else
            break;
    }
    A[i] = Tmp;
}

void HeapSort(long A[], long N){
    long i;
    for (i = N / 2; i >= 0; --i)
        BuildHeap(A, i, N); 		//构造堆
    for(i=N-1;i>0;--i){
        swap(&A[0],&A[i]);        //将最大元素(根)与数组末尾元素交换,从而删除最大元素,重新构造堆
        BuildHeap(A, 0, i);
    }
}

void QuickSort(long *arr, long maxlen, long begin, long end){
    long i, j;
    if (begin < end) {
        i = begin + 1;
        j = end;
        while (i < j) {
            if(arr[i] > arr[begin]){
                swap(&arr[i], &arr[j]);
                j--;
            } else {
                i++;
            }
        }
        if (arr[i] >= arr[begin]){
            i--;
        }
        swap(&arr[begin], &arr[i]);
        QuickSort(arr, maxlen, begin, i);
        QuickSort(arr, maxlen, j, end);
    } 
}

void putout(long *arr,long size){
    for (int i=0;i<size;i++) printf("%ld\n",arr[i]);
    putchar('\n'); 
}

int main( ){
    long size = ARRAY; 
    long arr[size]; 
    int i;
	double a[10],sum=0.0;
    clock_t start[10],end[10]; 
      
    printf("本次数据量大小为%ld,算法为归并排序:\n",size);
    for (i=0;i<10;i++){
    	BuildArray(arr,size); 
    	start[i] =clock();//or time(&start);
//		InsertionSort(arr, size); 
//		HeapSort(arr, size); 
//		QuickSort(arr, size, 0, size-1); 
		MergeSort(arr,0,size-1); 
		end[i] =clock();
    	a[i]=((double)end[i]-start[i])/CLK_TCK;
    	printf("a[%d]=%.4f\n",i,a[i]);
    	sum+=a[i];
	}
	printf("sum=%.4f\n",sum);
//    putout(arr,size);
}

代码随意取用,如果能点个赞或者关注我会更加乐意继续分享其他代码~
当然,如果对我的代码有什么优化建议可以在评论区留言或者私信发给我,那么这篇就先写到这里~

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

邵政道

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值