归并排序和快速排序比较【算法设计与分析实验报告】
下面的源代码是修改的了时间差精确到了纳秒级别的了,但是还是感觉很有误差。无论怎么测,总是快排比归并快,即使是测试数据的数组长度在10以内。
前面一样的程序写的是时间精确到微秒级的,数组长度大概在一万以内的,就是归并排序快了,大于这个长度的快速排序比较快。综合上面的情况,数组小时,二者时间差也不会太多,所以个人认为还是快速排序比较好了,唉还是觉得归并比较简单好写,弱爆了啊。。。
#include<cstdio> #include<Windows.h> #include<ctime> #include<cstdlib> #include<cstring> #include<iostream> using namespace std; const int maxn = 100000000; /* maxn 为数组最大值 */ /* *a[]为随机产生的数组 , b[]复制随机数组,t[]用于归并排序,暂时保存a[] */ int a[maxn]; int b[maxn], t[maxn]; int n; /* n为要比较的数的个数 */ /* *对数组下标从 p到r之间的数进行排序 *使得前面的数全都不大于基准元, 后面的数不小于基准元 */ int partition(int p, int r) { int i = p; int j = r+1; int x = a[p]; while(true) { while(a[++i] < x && i < r); while(a[--j] > x); if(i >= j) break; //swap(a, i, j); int temp = a[i]; a[i] = a[j]; a[j] = temp; } a[p] = a[j]; a[j] = x; return j; /* 返回基准元排好序后的位置 */ } int randomizedPartition(int p, int r) /* 对基准元进行处理 */ { int i = rand() % (r-p+1) + p; /* 产生p 到 q 之间的随机数 i */ int temp = a[i]; /* 交换随机位置到开始位置,使其成为基准元 */ a[i] = a[p]; a[p] = temp; return partition(p, r); } void randomizedQuickSort(int p, int r) /* 快速排序 */ { if(p < r) { int q = randomizedPartition(p, r); /* 分割 */ randomizedQuickSort(p, q-1); /* 从两边分别排序 */ randomizedQuickSort(q+1, r); } } void merge_sort(int *a, int x, int y, int *t) /* 归并排序 */ { if(y-x > 1) { int m = (y-x)/2 + x; /* 取中间 */ int p = x, q = m, i = x; merge_sort(b, p, m, t); /* 两边分别排序 */ merge_sort(b, m, y, t); while(p < m && q < y) { if(b[p] <= b[q]) t[i++] = b[p++]; else t[i++] = b[q++]; } while(p < m) t[i++] = b[p++]; while(q < y) t[i++] = b[q++]; for(i = x; i < y; i++) /* 将排序好的部分重新存入数组 a[]*/ b[i] = t[i]; } } int main() { printf("请输入要排序比较的个数 n ( n <= 100000000 ): "); while(scanf("%d", &n) != EOF) { LARGE_INTEGER begin, end; //double tstart, tend, MergeSortCost, QuickSortCost; long long MergeSortCost, QuickSortCost; memset(a, 0, sizeof(a)); /* 清空数组为0 */ for(int i = 0; i < n; i++) /* 生成随机数 */ { a[i] = rand(); b[i] = a[i]; } QueryPerformanceCounter(&begin); // tstart = clock(); randomizedQuickSort(0, n-1); /* 快速排序 */ QueryPerformanceCounter(&end); //tend = clock(); QuickSortCost = end.QuadPart - begin.QuadPart; //tend - tstart; //for(int i = 0; i < n; i++) printf("%d ", a[i]); QueryPerformanceCounter(&begin); //tstart = clock(); merge_sort(b, 0, n, t); /* 归并排序 */ QueryPerformanceCounter(&end); //tend = clock(); MergeSortCost = end.QuadPart - begin.QuadPart; //tend - tstart; //for(int i = 0; i < n; i++) printf("%d ", b[i]); printf("快速排序耗时:%lld ns,归并排序耗时:%lldns\n\n\n", QuickSortCost*100, MergeSortCost*100); printf("如果要继续比较请继续输入比较的个数 n : "); } return 0; }
#include<cstdio> #include<Windows.h> #include<ctime> #include<cstdlib> #include<cstring> #include<iostream> using namespace std; const int maxn = 100000000; /* maxn 为数组最大值 */ /* *a[]为随机产生的数组 , b[]复制随机数组,t[]用于归并排序,暂时保存a[] */ int a[maxn]; int b[maxn], t[maxn]; int n; /* n为要比较的数的个数 */ /* *对数组下标从 p到r之间的数进行排序 *使得前面的数全都不大于基准元, 后面的数不小于基准元 */ int partition(int p, int r) { int i = p; int j = r+1; int x = a[p]; while(true) { while(a[++i] < x && i < r); while(a[--j] > x); if(i >= j) break; //swap(a, i, j); int temp = a[i]; a[i] = a[j]; a[j] = temp; } a[p] = a[j]; a[j] = x; return j; /* 返回基准元排好序后的位置 */ } int randomizedPartition(int p, int r) /* 对基准元进行处理 */ { int i = rand() % (r-p+1) + p; /* 产生p 到 q 之间的随机数 i */ int temp = a[i]; /* 交换随机位置到开始位置,使其成为基准元 */ a[i] = a[p]; a[p] = temp; return partition(p, r); } void randomizedQuickSort(int p, int r) /* 快速排序 */ { if(p < r) { int q = randomizedPartition(p, r); /* 分割 */ randomizedQuickSort(p, q-1); /* 从两边分别排序 */ randomizedQuickSort(q+1, r); } } void merge_sort(int *a, int x, int y, int *t) /* 归并排序 */ { if(y-x > 1) { int m = (y-x)/2 + x; /* 取中间 */ int p = x, q = m, i = x; merge_sort(b, p, m, t); /* 两边分别排序 */ merge_sort(b, m, y, t); while(p < m && q < y) { if(b[p] <= b[q]) t[i++] = b[p++]; else t[i++] = b[q++]; } while(p < m) t[i++] = b[p++]; while(q < y) t[i++] = b[q++]; for(i = x; i < y; i++) /* 将排序好的部分重新存入数组 a[]*/ b[i] = t[i]; } } int main() { printf("请输入要排序比较的个数 n ( n <= 100000000 ): "); while(scanf("%d", &n) != EOF) { LARGE_INTEGER begin, end; //double tstart, tend, MergeSortCost, QuickSortCost; long long MergeSortCost, QuickSortCost; memset(a, 0, sizeof(a)); /* 清空数组为0 */ for(int i = 0; i < n; i++) /* 生成随机数 */ { a[i] = rand(); b[i] = a[i]; } QueryPerformanceCounter(&begin); // tstart = clock(); randomizedQuickSort(0, n-1); /* 快速排序 */ QueryPerformanceCounter(&end); //tend = clock(); QuickSortCost = end.QuadPart - begin.QuadPart; //tend - tstart; //for(int i = 0; i < n; i++) printf("%d ", a[i]); QueryPerformanceCounter(&begin); //tstart = clock(); merge_sort(b, 0, n, t); /* 归并排序 */ QueryPerformanceCounter(&end); //tend = clock(); MergeSortCost = end.QuadPart - begin.QuadPart; //tend - tstart; //for(int i = 0; i < n; i++) printf("%d ", b[i]); printf("快速排序耗时:%lld ns,归并排序耗时:%lldns\n\n\n", QuickSortCost*100, MergeSortCost*100); printf("如果要继续比较请继续输入比较的个数 n : "); } return 0; }
下面截个纳秒级别的,感觉不是很精确的图吧.
通过此次算法分析两种排序方法的比较,我还学到了一些简单的头函数的使用.
一、关于随机数的产生。
/* *产生区间[a , b]之间的随机整数 */ #include<cstdio> #include<cstdlib> int main() { int a,b; while(scanf("%d%d", &a, &b) != EOF) { int ans = rand()%(b-a+1) + a; printf("%d\n", ans); } return 0; }
二、如何测试系统当前时间。
/* *微秒级时间测试 */ #include <time.h> //time.h是C/C++中的日期和时间头文件 #include<cstdio> #include<iostream> using namespace std; int main() { double tstart, tend, tcost; tstart = clock(); for(int i=0;i<10000000;i++); //do something tend = clock(); tcost = (double)(tend-tstart)/CLOCKS_PER_SEC; printf("%lf\n", tcost); cout<<CLOCKS_PER_SEC; // == 1000 ms return 0; }
/* *纳秒级时间测试一 ,来自周杰学长 */ #include <Windows.h> #include <stdio.h> int main() { LARGE_INTEGER li; QueryPerformanceCounter(&li); printf("%lld\n", li); QueryPerformanceCounter(&li); printf("%lld\n", li); return 0; }
/* *纳秒级时间测试二 :测试用时 ,来自周杰学长 */ #include <Windows.h> #include <stdio.h> int main() { LARGE_INTEGER begin, end; QueryPerformanceCounter(&begin); Sleep(0); // do something QueryPerformanceCounter(&end); long long duration = end.QuadPart - begin.QuadPart; printf("duration: %lldns\n", duration * 100); return 0; }