1. /*
  2. Copyright (c)2016,烟台大学计算机与控制工程学院
  3. All rights reserved.
  4. 文件名称:排序.cpp
  5. 作    者:   陈朋
  6. 完成日期:2016年12月15日
  7. 版 本 号:v1.0
  8. 问题描述:设计一个函数,产生一个至少5万条记录的数据集合。在同一数据集上,用直接
  9. 插入排序、冒泡排序、快速排序、直接选择排序、堆排序、归并排序、基数排序
  10. 等算法进行排序,记录所需要的时间,经过对比,得到对复杂度不同的各种算法
  11. 在运行时间方面的感性认识。
  12. 提示1:这一项目需要整合多种排序算法,可以考虑先建设排序算法库,作为我们
  13. 这门课算法库的收官之作;
  14. 提示2:本项目旨在获得对于复杂度不同算法的感性认识,由于数据分布特点、计算
  15. 机运行状态等不同,其结果并不能完全代替对算法复杂度的理论分析;
  16. 提示3:由于C语言标准提供的时间函数只精确到秒,几种O(nlog2n)级别的算法,在
  17. 5万条记录的压力下,并不能明显地看出优劣,可以忽略直接插入排序、冒泡
  18. 排序、直接选择排序这三种相对低效率的算法(以节约时间。若能够忍受他们
  19. 长时间地运行,请自便),成10倍地加大数据量,然后进行观察。
  20. 输入描述:无
  21. 程序输出:若干

1.测试用的主控程序——main.cpp

[cpp] view plaincopy
  1. #include <stdio.h>
  2. #include <malloc.h>
  3. #include <stdlib.h>
  4. #include <time.h>
  5. #include "sort.h"
  6. void GetLargeData(RecType *&R, int n)
  7. {
  8. srand(time(0));
  9. R=(RecType*)malloc(sizeof(RecType)*n);
  10. for(int i=0; i<n; i++)
  11. R[i].key= rand();  //产生0~RAND_MAX间的数
  12. printf("生成了%d条记录\n", n);
  13. }
  14. //调用某一排序算法完成排序,返回排序用时
  15. long Sort(RecType *&R, int n, void f(RecType*, int))
  16. {
  17. int i;
  18. long beginTime, endTime;
  19. RecType *R1=(RecType*)malloc(sizeof(RecType)*n);
  20. for (i=0;i<n;i++)
  21. R1[i]=R[i];
  22. beginTime = time(0);
  23. f(R1,n);
  24. endTime = time(0);
  25. free(R1);
  26. return endTime-beginTime;
  27. }
  28. //调用基数排序算法完成排序,返回排序用时
  29. long Sort1(RecType *&R, int n)
  30. {
  31. long beginTime, endTime;
  32. RadixRecType *p;
  33. CreateLink(p,R,n);
  34. beginTime = time(0);
  35. RadixSort(p);
  36. endTime = time(0);
  37. DestoryLink(p);
  38. return endTime-beginTime;
  39. }
  40. int main()
  41. {
  42. RecType *R;
  43. int n = MaxSize;   //测试中, MaxSize取50W
  44. GetLargeData(R, n);
  45. printf("各种排序花费时间:\n");
  46. printf("  直接插入排序:%ld\n", Sort(R, n, InsertSort));
  47. printf("  希尔排序:%ld\n", Sort(R, n, ShellSort));
  48. printf("  冒泡排序:%ld\n", Sort(R, n, BubbleSort));
  49. printf("  快速排序:%ld\n", Sort(R, n, QuickSort));
  50. printf("  直接选择排序:%ld\n", Sort(R, n, SelectSort));
  51. printf("  堆排序:%ld\n", Sort(R, n, HeapSort));
  52. printf("  归并排序:%ld\n", Sort(R, n, MergeSort));
  53. printf("  基数排序:%ld\n", Sort1(R, n));
  54. free(R);
  55. return 0;
  56. }

2.头文件 —— sort.h

[cpp] view plaincopy
  1. #ifndef SORT_H_INCLUDED
  2. #define SORT_H_INCLUDED
  3. #define MaxSize 50000      //最多的数据,取5万,只测试快速算法,可以往大调整
  4. //下面的符号常量和结构体针对基数排序
  5. #define Radix 10           //基数的取值
  6. #define Digits 10          //关键字位数
  7. typedef int KeyType;    //定义关键字类型
  8. typedef char InfoType[10];
  9. typedef struct          //记录类型
  10. {
  11. KeyType key;        //关键字项
  12. InfoType data;      //其他数据项,类型为InfoType
  13. } RecType;              //排序的记录类型定义
  14. typedef struct node
  15. {
  16. KeyType data;      //记录的关键字,同算法讲解中有差别
  17. struct node *next;
  18. } RadixRecType;
  19. void InsertSort(RecType R[],int n); //直接插入排序
  20. void ShellSort(RecType R[],int n);  //希尔排序算法
  21. void BubbleSort(RecType R[],int n); //冒泡排序
  22. void QuickSort(RecType R[],int n);  //快速排序
  23. void SelectSort(RecType R[],int n);  //直接选择排序
  24. void HeapSort(RecType R[],int n);  //堆排序
  25. void MergeSort(RecType R[],int n); //归并排序
  26. //下面函数支持基数排序
  27. void CreateLink(RadixRecType *&p,RecType R[],int n);   //创建基数排序用的链表
  28. void DestoryLink(RadixRecType *&p); //释放基数排序用的链表
  29. void RadixSort(RadixRecType *&p); //基数排序
  30. #endif // SORT_H_INCLUDED

3.算法的实现—— sort.cpp

[cpp] view plaincopy
  1. #include "sort.h"
  2. #include <malloc.h>
  3. //1. 对R[0..n-1]按递增有序进行直接插入排序
  4. void InsertSort(RecType R[],int n)
  5. {
  6. int i,j;
  7. RecType tmp;
  8. for (i=1; i<n; i++)
  9. {
  10. tmp=R[i];
  11. j=i-1;            //从右向左在有序区R[0..i-1]中找R[i]的插入位置
  12. while (j>=0 && tmp.key<R[j].key)
  13. {
  14. R[j+1]=R[j]; //将关键字大于R[i].key的记录后移
  15. j--;
  16. }
  17. R[j+1]=tmp;      //在j+1处插入R[i]
  18. }
  19. }
  20. //2. 希尔排序算法
  21. void ShellSort(RecType R[],int n)
  22. {
  23. int i,j,gap;
  24. RecType tmp;
  25. gap=n/2;                //增量置初值
  26. while (gap>0)
  27. {
  28. for (i=gap; i<n; i++) //对所有相隔gap位置的所有元素组进行排序
  29. {
  30. tmp=R[i];
  31. j=i-gap;
  32. while (j>=0 && tmp.key<R[j].key)//对相隔gap位置的元素组进行排序
  33. {
  34. R[j+gap]=R[j];
  35. j=j-gap;
  36. }
  37. R[j+gap]=tmp;
  38. j=j-gap;
  39. }
  40. gap=gap/2;  //减小增量
  41. }
  42. }
  43. //3. 冒泡排序
  44. void BubbleSort(RecType R[],int n)
  45. {
  46. int i,j,exchange;
  47. RecType tmp;
  48. for (i=0; i<n-1; i++)
  49. {
  50. exchange=0;
  51. for (j=n-1; j>i; j--)   //比较,找出最小关键字的记录
  52. if (R[j].key<R[j-1].key)
  53. {
  54. tmp=R[j];  //R[j]与R[j-1]进行交换,将最小关键字记录前移
  55. R[j]=R[j-1];
  56. R[j-1]=tmp;
  57. exchange=1;
  58. }
  59. if (exchange==0)    //没有交换,即结束算法
  60. return;
  61. }
  62. }
  63. //4. 对R[s]至R[t]的元素进行快速排序
  64. void QuickSortR(RecType R[],int s,int t)
  65. {
  66. int i=s,j=t;
  67. RecType tmp;
  68. if (s<t)                //区间内至少存在两个元素的情况
  69. {
  70. tmp=R[s];           //用区间的第1个记录作为基准
  71. while (i!=j)        //从区间两端交替向中间扫描,直至i=j为止
  72. {
  73. while (j>i && R[j].key>=tmp.key)
  74. j--;        //从右向左扫描,找第1个小于tmp.key的R[j]
  75. R[i]=R[j];      //找到这样的R[j],R[i]"R[j]交换
  76. while (i<j && R[i].key<=tmp.key)
  77. i++;        //从左向右扫描,找第1个大于tmp.key的记录R[i]
  78. R[j]=R[i];      //找到这样的R[i],R[i]"R[j]交换
  79. }
  80. R[i]=tmp;
  81. QuickSortR(R,s,i-1);     //对左区间递归排序
  82. QuickSortR(R,i+1,t);     //对右区间递归排序
  83. }
  84. }
  85. //4. 快速排序辅助函数,对外同其他算法统一接口,内部调用递归的快速排序
  86. void QuickSort(RecType R[],int n)
  87. {
  88. QuickSortR(R, 0, n-1);
  89. }
  90. //5. 直接选择排序
  91. void SelectSort(RecType R[],int n)
  92. {
  93. int i,j,k;
  94. RecType temp;
  95. for (i=0; i<n-1; i++)           //做第i趟排序
  96. {
  97. k=i;
  98. for (j=i+1; j<n; j++)   //在当前无序区R[i..n-1]中选key最小的R[k]
  99. if (R[j].key<R[k].key)
  100. k=j;            //k记下目前找到的最小关键字所在的位置
  101. if (k!=i)               //交换R[i]和R[k]
  102. {
  103. temp=R[i];
  104. R[i]=R[k];
  105. R[k]=temp;
  106. }
  107. }
  108. }
  109. //6. 堆排序辅助之——调整堆
  110. void sift(RecType R[],int low,int high)
  111. {
  112. int i=low,j=2*i;                        //R[j]是R[i]的左孩子
  113. RecType temp=R[i];
  114. while (j<=high)
  115. {
  116. if (j<high && R[j].key<R[j+1].key)  //若右孩子较大,把j指向右孩子
  117. j++;                                //变为2i+1
  118. if (temp.key<R[j].key)
  119. {
  120. R[i]=R[j];                          //将R[j]调整到双亲结点位置上
  121. i=j;                                //修改i和j值,以便继续向下筛选
  122. j=2*i;
  123. }
  124. else break;                             //筛选结束
  125. }
  126. R[i]=temp;                                  //被筛选结点的值放入最终位置
  127. }
  128. //6. 堆排序
  129. void HeapSort(RecType R[],int n)
  130. {
  131. int i;
  132. RecType temp;
  133. for (i=n/2; i>=1; i--) //循环建立初始堆
  134. sift(R,i,n);
  135. for (i=n; i>=2; i--) //进行n-1次循环,完成推排序
  136. {
  137. temp=R[1];       //将第一个元素同当前区间内R[1]对换
  138. R[1]=R[i];
  139. R[i]=temp;
  140. sift(R,1,i-1);   //筛选R[1]结点,得到i-1个结点的堆
  141. }
  142. }
  143. //7.归并排序辅助1——合并有序表
  144. void Merge(RecType R[],int low,int mid,int high)
  145. {
  146. RecType *R1;
  147. int i=low,j=mid+1,k=0; //k是R1的下标,i、j分别为第1、2段的下标
  148. R1=(RecType *)malloc((high-low+1)*sizeof(RecType));  //动态分配空间
  149. while (i<=mid && j<=high)       //在第1段和第2段均未扫描完时循环
  150. if (R[i].key<=R[j].key)     //将第1段中的记录放入R1中
  151. {
  152. R1[k]=R[i];
  153. i++;
  154. k++;
  155. }
  156. else                            //将第2段中的记录放入R1中
  157. {
  158. R1[k]=R[j];
  159. j++;
  160. k++;
  161. }
  162. while (i<=mid)                      //将第1段余下部分复制到R1
  163. {
  164. R1[k]=R[i];
  165. i++;
  166. k++;
  167. }
  168. while (j<=high)                 //将第2段余下部分复制到R1
  169. {
  170. R1[k]=R[j];
  171. j++;
  172. k++;
  173. }
  174. for (k=0,i=low; i<=high; k++,i++) //将R1复制回R中
  175. R[i]=R1[k];
  176. }
  177. //7. 归并排序辅助2——一趟归并
  178. void MergePass(RecType R[],int length,int n)    //对整个数序进行一趟归并
  179. {
  180. int i;
  181. for (i=0; i+2*length-1<n; i=i+2*length)     //归并length长的两相邻子表
  182. Merge(R,i,i+length-1,i+2*length-1);
  183. if (i+length-1<n)                       //余下两个子表,后者长度小于length
  184. Merge(R,i,i+length-1,n-1);          //归并这两个子表
  185. }
  186. //7. 归并排序
  187. void MergeSort(RecType R[],int n)           //自底向上的二路归并算法
  188. {
  189. int length;
  190. for (length=1; length<n; length=2*length) //进行log2n趟归并
  191. MergePass(R,length,n);
  192. }
  193. //以下基数排序,为了统一测试有改造
  194. //8. 基数排序的辅助函数,创建基数排序用的链表
  195. void CreateLink(RadixRecType *&p,RecType R[],int n)   //采用后插法产生链表
  196. {
  197. int i;
  198. RadixRecType *s,*t;
  199. for (i=0; i<n; i++)
  200. {
  201. s=(RadixRecType *)malloc(sizeof(RadixRecType));
  202. s->data = R[i].key;
  203. if (i==0)
  204. {
  205. p=s;
  206. t=s;
  207. }
  208. else
  209. {
  210. t->next=s;
  211. t=s;
  212. }
  213. }
  214. t->next=NULL;
  215. }
  216. //8. 基数排序的辅助函数,释放基数排序用的链表
  217. void DestoryLink(RadixRecType *&p)
  218. {
  219. RadixRecType *q;
  220. while(p!=NULL)
  221. {
  222. q=p->next;
  223. free(p);
  224. p=q;
  225. }
  226. return;
  227. }
  228. //8. 实现基数排序:*p为待排序序列链表指针,基数R和关键字位数D已经作为符号常量定义好
  229. void RadixSort(RadixRecType *&p)
  230. {
  231. RadixRecType *head[Radix],*tail[Radix],*t; //定义各链队的首尾指针
  232. int i,j,k;
  233. unsigned int d1, d2=1;   //用于分离出第i位数字,见下面的注释
  234. for (i=1; i<=Digits; i++)                  //从低位到高位循环
  235. {
  236. //分离出倒数第i位数字,先通过对d1=10^i取余,得到其后i位,再通过整除d2=10^(i-1)得到第i位
  237. //例如,分离出倒数第1位,即个位数,先对d1=10取余,再整除d2=1
  238. //再例如,分离出倒数第2位,即十位数,先对d1=100取余,再整除d2=10
  239. //循环之前,d2已经初始化为1,在这一层循环末增加10倍
  240. //下面根据d2,得到d1的值
  241. d1=d2*10;
  242. for (j=0; j<Radix; j++)                 //初始化各链队首、尾指针
  243. head[j]=tail[j]=NULL;
  244. while (p!=NULL)                 //对于原链表中每个结点循环
  245. {
  246. k=(p->data%d1)/d2;           //分离出第i位数字k
  247. if (head[k]==NULL)          //进行分配
  248. {
  249. head[k]=p;
  250. tail[k]=p;
  251. }
  252. else
  253. {
  254. tail[k]->next=p;
  255. tail[k]=p;
  256. }
  257. p=p->next;                  //取下一个待排序的元素
  258. }
  259. p=NULL;                         //重新用p来收集所有结点
  260. for (j=0; j<Radix; j++)             //对于每一个链队循环
  261. if (head[j]!=NULL)          //进行收集
  262. {
  263. if (p==NULL)
  264. {
  265. p=head[j];
  266. t=tail[j];
  267. }
  268. else
  269. {
  270. t->next=head[j];
  271. t=tail[j];
  272. }
  273. }
  274. t->next=NULL;                   //最后一个结点的next域置NULL
  275. //下面更新用于分离出第i位数字的d2
  276. d2*=10;
  277. }
  278. }

第十五周项目2 - 大数据集上排序算法性能的体验相关推荐

  1. 第十六周上机实践—项目2—大数据集上排序算法性能的体验

    /* *Copyright(c) 2015,烟台大学计算机学院 *All rights reserved. *文件名称:test.cpp *作者:林莉 *完成日期:2015年12月18日 *版本:v1 ...

  2. 第十五周 项目一 (3)验证交换排序

    /* * Copyright (c)2017,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名称:项目1-3.cbp * 作 者:孙仁圆 * 完成日期:2017年 ...

  3. 第十五周 项目三 归并排序算法的改进

    /* * Copyright (c)2017,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名称:项目3.cpp * 作 者:孙仁圆 * 完成日期:2017年12 ...

  4. 第十五周项目1-验证算法-冒泡排序

    /* *Copyright (c) 2017,烟台大学计算机与控制工程学院 *All rights reserved. *文件名称:项目1-冒泡排序 *作 者:董丽娟 *完成日期:2017年12月7日 ...

  5. 第十五周项目二-洗牌(范形程序设计)

    /* *Copyright(c)2016,烟台大学计算机与控制工程学院 *All rights reserved *文件名称:123.cpp *作 者:王蕊 *完成日期:2016年6月7日 *版 本 ...

  6. 第十五周项目一-程序填空(范型程序设计)

    /* *Copyright(c)2016,烟台大学计算机与控制工程学院 *All rights reserved *文件名称:123.cpp *作 者:王蕊 *完成日期:2016年6月7日 *版 本 ...

  7. 第十五周项目1-打入“内部”寻“内幕”

    下面是一段使用了指针的程序.请利用"单步"执行的方式运行程序,深刻理解"指针变量存储的是地址值"."通过指针变量间接访问"等概念. /* * ...

  8. 第十五周项目一----哈希表的运算及实现

    /* 烟台大学计算机与控制工程学院 作 者:孙潇 完成日期:2015年12月11日 问题描述:运行并本周视频中所讲过的算法,观察结果并领会算法. 写程序建立序列{16, 74, 60, 43, 54, ...

  9. 第十五周项目二----用哈希法组织关键字之链地址法

    /*烟台大学计算机与控制工程学院 作者:孙潇 时间:2015年12月11日 问题描述: 已知一个关键字序列为if.while.for.case.do.break.else.struct.union.i ...

  10. 第十五周项目二-----用哈希法组织关键字之线性探测法

    /*烟台大学计算机与控制工程学院 作者:孙潇 时间:2015年12月11日 问题描述: 已知一个关键字序列为if.while.for.case.do.break.else.struct.union.i ...

最新文章

  1. Array 数组去重 总结10方法(7)
  2. 这些 Python 不为人知的「坑」,躲都躲不开
  3. [POJ]Zipper[动态规划]
  4. 3种Python数据结构,13种创建方法,这个总结,超赞!
  5. linux更新驱动脚本,Linux 第一个驱动程序编写
  6. Qemu(纯软实现)架构+KVM(基于kernel模拟硬件)原理(一)
  7. 快讯丨业界首本云网络图书发布
  8. fi sap 凭证冲销 稅_sap如何冲销凭证 SAP技术篇之一SAP凭证冲销总结 - 电脑常识 - 服务器之家...
  9. 图像处理 灰度变换与空间滤波
  10. 目标检测各类数据集格式互转以及处理方法(VOC, COCO, txt)
  11. 怎么将word转换成excel表格格式最简单
  12. 小小盗号VC实现原理
  13. 阿里C/C++面试题
  14. 玫瑰编程--python
  15. 深度学习(李沐)—————Softmax回归
  16. Java excel导出压缩zip并加密(拿起即用,有用请点赞,不做白嫖怪!)
  17. java的mvc模式是什么_什么是mvc模式
  18. 【算法详解】splay的初步了解
  19. 如何选择低价高防服务器?
  20. A/libc:fatal signal 11(SIGSEGV).code 1, fault addr 0x0 in tid 26488 (VideoEncoder)

热门文章

  1. 前端谷歌浏览器显示海康rtsp视频
  2. 关于两仪、三才、四象、五行、六合、七星、八卦、九宫、十方、中医的现代科学猜想全解
  3. 5G成鸡肋?运营商可能冷处理,中国移动则加快建设4G的FDD900
  4. 为什么程序员喜欢用dark mode深色模式
  5. 蒙特卡洛光线追踪技术
  6. 读书笔记-计算机视觉
  7. matlab 科研绘图
  8. 关于传奇客户端及补丁文件相关合集
  9. python刘卫国实验题_刘卫国c 程序设计实践教程答案
  10. 各种学习网址总结-程序猿值得拥有 持更