本篇博客实现了 1.冒泡排序 2.冒泡排序的一种优化(当某次冒泡没有进行交换时,退出循环) 3.选择排序 4.归并排序 5.快速排序。

主要是源码的实现,并将自己在敲的过程中所遇到的一些问题记录下来。

全局定义与相关声明:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. using namespace std;
  5. int num[100005]; //存储数组
  6. void swap1(int i, int j) //交换函数swap
  7. {
  8. int t = num[i];
  9. num[i] = num[j];
  10. num[j] = t;
  11. }
  12. /*Printnum 输出*/
  13. void Printnum(int n) //输出排序完成的数组
  14. {
  15. for (int i = 1; i <= n; i++) {
  16. cout << num[i] << " ";
  17. }
  18. cout << endl;
  19. }

1.冒泡排序

  1. /*Bubble_Sort 冒泡排序*/
  2. void Bubble_Sort(int n)
  3. {
  4. int i, j;
  5. for (i = 1; i <= n; i++) //遍历n次
  6. {
  7. for (j = 1; j <= n-i; j++) //每次都把最大数往后排,缩小范围
  8. {
  9. if (num[j] > num[j+1])
  10. {
  11. swap1(j, j+1);
  12. }
  13. }
  14. }
  15. }

冒泡的思想:不断把范围中的最大数往后排,排完之后缩小范围;以上过程执行n次。

个人小结:思想很简单,但是太久不碰真的会忘记。

2.冒泡排序的优化

  1. void Bubble_Sort_Better(int n)
  2. {
  3. int i, j;
  4. for (i = 1; i <= n; i++)
  5. {
  6. bool flag = true;
  7. for (j = 1; j <= n-i; j++)
  8. {
  9. if (num[j] > num[j+1])
  10. {
  11. flag = false;
  12. swap1(j, j+1);
  13. }
  14. }
  15. if (flag) break; //某一次遍历没有发生交换时,结束
  16. }
  17. }

优化的思想:当某一次冒泡没有交换任何数时,则说明当前范围内序列有序,结束循环。

3.选择排序

  1. /*Selection_Sort 选择排序*/
  2. void Selection_Sort(int n)
  3. {
  4. int i, j;
  5. int rcd;
  6. for (i = 1; i <= n; i++)
  7. {
  8. rcd = i;
  9. for (j = i+1; j <= n; j++)
  10. {
  11. if (num[j] < num[rcd]) //找出i+1=>n范围内的最小元并前移
  12. {
  13. rcd = j;
  14. }
  15. }
  16. swap1(i, rcd);
  17. }
  18. }

思想:找出范围i => n内最小的数,用rcd(初始化为i)记录其位置,之后与寻找范围内的第一个数num[i]进行交换,保证i+1 => n的所有数均大于num[i]。

4.归并排序:

  1. /*Merge_Sort 归并排序*/
  2. int temp[100005];
  3. void Merge_Array(int l1, int r1, int l2, int r2)
  4. {
  5. int p1 = l1;
  6. int p2 = l2;
  7. int i = 1;
  8. memset(temp, 0, sizeof(temp));
  9. for (i = l1; i <= r2; i++)
  10. {
  11. if (p1 > r1)
  12. {
  13. temp[i] = num[p2++];
  14. continue;
  15. }
  16. if (p2 > r2)
  17. {
  18. temp[i] = num[p1++];
  19. continue;
  20. }
  21. if (num[p1] < num[p2])
  22. {
  23. temp[i] = num[p1++];
  24. continue;
  25. }
  26. else
  27. {
  28. temp[i] = num[p2++];
  29. continue;
  30. }
  31. }
  32. for (i = l1; i <= r2; i++)
  33. {
  34. num[i] = temp[i];
  35. }
  36. }
  37. void Merge_Sort(int l, int r)
  38. {
  39. if (l < r)
  40. {
  41. int mid = (l+r)/2;
  42. Merge_Sort(l, mid); //l => mid
  43. Merge_Sort(mid+1, r); //mid+1 => r
  44. Merge_Array(l, mid, mid+1, r); //l => mid => mid+1 => r
  45. }
  46. }

思想可以参考:白话经典算法系列之五 归并排序的实现

大概的思路是,先并后归,将范围二分,分别递归排序之后再进行合并(利用一个额外的数组temp)。

个人小结:

1.看似简单,实现起来总是会出问题;动手吧。

2.一定要注意:递归选取的范围,取了mid = (l+r)/2之后,左边的一半范围为[l => mid],右边的一半范围为[mid+1 => r]。原因可以考虑以下情况:两个数3 1进行排序,mid = 1,如果选取的范围为[l => mid-1]和[mid => r](这里是[1 => 1]和[1 => 2]),则会出现死循环。

5.QuickSort快速排序

  1. int Quick_Sort_Adjust(int l, int r)
  2. {
  3. int key = l; //选取第一个元素为基准值
  4. int a, b;
  5. a = l+1;
  6. b = r;
  7. while (a < b)
  8. {
  9. bool out_bound = false;
  10. while (1)
  11. {
  12. if (num[a] > num[key]) break;
  13. a++;
  14. if (a > r)
  15. {
  16. out_bound = true;
  17. break;
  18. }
  19. }
  20. while (1)
  21. {
  22. if (num[b] < num[key]) break;
  23. b--;
  24. if (b < l)
  25. {
  26. out_bound = true;
  27. break;
  28. }
  29. }
  30. if (out_bound || a >= b) break; //如果出现越界或a>=b直接结束
  31. swap1(a, b);
  32. a++;
  33. b--;
  34. }
  35. swap1(key, a-1);
  36. return a-1;
  37. }
  38. void Quick_Sort(int l, int r)
  39. {
  40. if (l < r)
  41. {
  42. int mid = Quick_Sort_Adjust(l, r);
  43. Quick_Sort(l, mid-1); //l => mid-1
  44. Quick_Sort(mid+1, r); //mid+1 => r
  45. }
  46. }

思想可以参考:白话经典算法系列之六 快速排序 快速搞定

思路上文讲的很清楚了,建议在纸上模拟以下四种情况:

  1. 1.n = 7
  2. 1 3 1 2 -1 8 9
  3. 2.n = 7
  4. 1 1 1 1 1 1 1
  5. 3.n = 7
  6. 7 6 5 4 3 2 1
  7. 4.n = 7
  8. 7 1 1 1 1 1 1

个人小结:

1.同样的,自己敲一遍能够发现一堆问题。

2.一定要注意,当出现以下两种情况时:(1)i>j(这里的代码是a>b) (2)i、j越界 应该立即退出循环。

3.递归范围的选择,在基准值num[key]和num[mid]交换之后,接下来的递归范围应该为[l => mid-1]和[mid+1 => r],因为[l => mid-1]范围内的所有值都小于num[mid],[mid+1 => r]内的所有值都大于num[mid];如果选取范围对mid取等,会出现上文中两个数(如 3 1)的死循环。

4.这里选择的基准是第一个数,快速排序还有很多改进版本,如随机选择基准数,区间内数据较少时直接用别的方法排序以减小递归深度。

完整代码如下:

  1. //
  2. // main.cpp
  3. // Sort
  4. //
  5. // Created by wasdns on 16/12/25.
  6. // Copyright © 2016年 wasdns. All rights reserved.
  7. //
  8. #include <iostream>
  9. #include <cstdio>
  10. #include <cstring>
  11. using namespace std;
  12. /*存储数组定义*/
  13. int num[100005];
  14. void swap1(int i, int j)
  15. {
  16. int t = num[i];
  17. num[i] = num[j];
  18. num[j] = t;
  19. }
  20. /*Printnum 输出*/
  21. void Printnum(int n)
  22. {
  23. for (int i = 1; i <= n; i++) {
  24. cout << num[i] << " ";
  25. }
  26. cout << endl;
  27. }
  28. /*Bubble_Sort 冒泡排序*/
  29. void Bubble_Sort(int n)
  30. {
  31. int i, j;
  32. for (i = 1; i <= n; i++) //遍历n次
  33. {
  34. for (j = 1; j <= n-i; j++) //每次都把最大数往后排,缩小范围
  35. {
  36. if (num[j] > num[j+1])
  37. {
  38. swap1(j, j+1);
  39. }
  40. }
  41. }
  42. }
  43. void Bubble_Sort_Better(int n)
  44. {
  45. int i, j;
  46. for (i = 1; i <= n; i++)
  47. {
  48. bool flag = true;
  49. for (j = 1; j <= n-i; j++)
  50. {
  51. if (num[j] > num[j+1])
  52. {
  53. flag = false;
  54. swap1(j, j+1);
  55. }
  56. }
  57. if (flag) break; //某一次遍历没有发生交换时,结束
  58. }
  59. }
  60. /*Selection_Sort 选择排序*/
  61. void Selection_Sort(int n)
  62. {
  63. int i, j;
  64. int rcd;
  65. for (i = 1; i <= n; i++)
  66. {
  67. rcd = i;
  68. for (j = i+1; j <= n; j++)
  69. {
  70. if (num[j] < num[rcd]) //找出i+1=>n范围内的最小元并前移
  71. {
  72. rcd = j;
  73. }
  74. }
  75. swap1(i, rcd);
  76. }
  77. }
  78. /*Merge_Sort 归并排序*/
  79. int temp[100005];
  80. void Merge_Array(int l1, int r1, int l2, int r2)
  81. {
  82. int p1 = l1;
  83. int p2 = l2;
  84. int i = 1;
  85. memset(temp, 0, sizeof(temp));
  86. for (i = l1; i <= r2; i++)
  87. {
  88. if (p1 > r1)
  89. {
  90. temp[i] = num[p2++];
  91. continue;
  92. }
  93. if (p2 > r2)
  94. {
  95. temp[i] = num[p1++];
  96. continue;
  97. }
  98. if (num[p1] < num[p2])
  99. {
  100. temp[i] = num[p1++];
  101. continue;
  102. }
  103. else
  104. {
  105. temp[i] = num[p2++];
  106. continue;
  107. }
  108. }
  109. for (i = l1; i <= r2; i++)
  110. {
  111. num[i] = temp[i];
  112. }
  113. }
  114. void Merge_Sort(int l, int r)
  115. {
  116. if (l < r)
  117. {
  118. int mid = (l+r)/2;
  119. Merge_Sort(l, mid); //l => mid
  120. Merge_Sort(mid+1, r); //mid+1 => r
  121. Merge_Array(l, mid, mid+1, r); //l => mid => mid+1 => r
  122. }
  123. }
  124. /*Quick_Sort 快速排序*/
  125. int Quick_Sort_Adjust(int l, int r)
  126. {
  127. int key = l; //选取第一个元素为基准值
  128. int a, b;
  129. a = l+1;
  130. b = r;
  131. while (a < b)
  132. {
  133. bool out_bound = false;
  134. while (1)
  135. {
  136. if (num[a] > num[key]) break;
  137. a++;
  138. if (a > r)
  139. {
  140. out_bound = true;
  141. break;
  142. }
  143. }
  144. while (1)
  145. {
  146. if (num[b] < num[key]) break;
  147. b--;
  148. if (b < l)
  149. {
  150. out_bound = true;
  151. break;
  152. }
  153. }
  154. if (out_bound || a >= b) break; //如果出现越界或a>=b直接结束
  155. swap1(a, b);
  156. a++;
  157. b--;
  158. }
  159. swap1(key, a-1);
  160. return a-1;
  161. }
  162. void Quick_Sort(int l, int r)
  163. {
  164. if (l < r)
  165. {
  166. int mid = Quick_Sort_Adjust(l, r);
  167. Quick_Sort(l, mid-1); //l => mid-1
  168. Quick_Sort(mid+1, r); //mid+1 => r
  169. }
  170. }
  171. int main()
  172. {
  173. int n;
  174. cin >> n;
  175. for (int i = 1; i <= n; i++)
  176. {
  177. cin >> num[i];
  178. }
  179. int option;
  180. cin >> option;
  181. if (option == 1)
  182. {
  183. cout << "Bubble_Sort" << endl;
  184. Bubble_Sort(n);
  185. }
  186. else if (option == 2)
  187. {
  188. cout << "Bubble_Sort_Better" << endl;
  189. Bubble_Sort_Better(n);
  190. }
  191. else if (option == 3)
  192. {
  193. cout << "Selection_Sort" << endl;
  194. Selection_Sort(n);
  195. }
  196. else if (option == 4)
  197. {
  198. cout << "Merge_Sort" << endl;
  199. Merge_Sort(1, n);
  200. }
  201. else if (option == 5)
  202. {
  203. cout << "Quick_Sort" << endl;
  204. Quick_Sort(1, n);
  205. }
  206. Printnum(n);
  207. return 0;
  208. }

2016/12/26

DataStructure 排序 源码实现的更多相关文章

  1. html5 Sortable.js 拖拽排序源码分析

    最近公司项目经常用到一个拖拽 Sortable.js插件,所以有空的时候看了 Sortable.js 源码,总共1300多行这样,写的挺完美的.   本帖属于原创,转载请出名出处. 官网http:// ...

  2. 解读 v8 排序源码

    前言 v8 是 Chrome 的 JavaScript 引擎,其中关于数组的排序完全采用了 JavaScript 实现. 排序采用的算法跟数组的长度有关,当数组长度小于等于 10 时,采用插入排序,大 ...

  3. C#冒泡法排序源码

    如下内容内容是关于C#冒泡法排序的内容,应该对码农有一些用途. int[] myArray = new int[] { 10, 8, 3, 5, 6, 7, 4, 6, 9 }; for( int j ...

  4. springboot源码解析-管中窥豹系列之排序(五)

    一.前言 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...

  5. spring源码分析系列 (1) spring拓展接口BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor

    更多文章点击--spring源码分析系列 主要分析内容: 一.BeanFactoryPostProcessor.BeanDefinitionRegistryPostProcessor简述与demo示例 ...

  6. laravel源码解析

    本专栏系列文章已经收录到 GitBooklaravel源码解析 Laravel Passport——OAuth2 API 认证系统源码解析(下)laravel源码解析 Laravel Passport ...

  7. [Guava源码分析]Ordering:排序

    我的技术博客经常被流氓网站恶意爬取转载.请移步原文:http://www.cnblogs.com/hamhog/p/3876466.html,享受整齐的排版.有效的链接.正确的代码缩进.更好的阅读体验 ...

  8. 三种排序算法python源码——冒泡排序、插入排序、选择排序

    最近在学习python,用python实现几个简单的排序算法,一方面巩固一下数据结构的知识,另一方面加深一下python的简单语法. 冒泡排序算法的思路是对任意两个相邻的数据进行比较,每次将最小和最大 ...

  9. Solr4.8.0源码分析(6)之非排序查询

    Solr4.8.0源码分析(6)之非排序查询 上篇文章简单介绍了Solr的查询流程,本文开始将详细介绍下查询的细节.查询主要分为排序查询和非排序查询,由于两者走的是两个分支,所以本文先介绍下非排序的查 ...

随机推荐

  1. 拖拽对DOM的影响

    前一段时间公司要对上传列表中多文本输入框添加富文本编辑功能,所以最初的想法是引入富文本编辑器插件,对每个多文本输入框实例化一次.但是上传列表还有一个可以拖拽排序的功能,在初次实例化以后,再拖拽元素就会 ...

  2. mysql 最大连接数 & 连接池

    MySQL最大连接数 关于最大连接数:http://mg123.lofter.com/post/1a5f3e_996f838 可以通过修改配置文件(默认/etc/my.cnf)中的"mysq ...

  3. JS 对数组的常用处理

    首先写游戏的时候,JSON字符串转成OBJECT的时候,希望做个数组随机排序的方法如下: //用Math.random()函数生成0~1之间的随机数与0.5比较,返回-1或1 function ran ...

  4. request response

    request 和 response 这两个对象是出现在service方法中.service方法是用来接收请求处理请求,完成响应的.     接受请求指的就是request对象     完成响应指的就 ...

  5. MySQL 5.7 mysqlpump 备份工具说明

    背景: MySQL5.7之后多了一个备份工具:mysqlpump.它是mysqldump的一个衍生,mysqldump就不多说明了,现在看看mysqlpump到底有了哪些提升,可以查看官方文档,这里针 ...

  6. Android编程容易犯的错误之一

    1.设置TextView的文本颜色 TextView tv; ... tv.setTextColor(R.color.white); 其实这样设置的颜色是 R.color.white的资源ID值所代表 ...

  7. Python~切片Slice

          [:] [:10] [-10:]       [':10:2]                                  

  8. 【控制iOS7兼容iOS6 状态栏的显示不完全 简单缩写】

    #if ios7 self.automaticallyAdjustsScrollViewInsets = YES; self.edgesForExtendedLayout = UIRectEdgeNo ...

  9. Linux网络管理1---(Linux配置IP地址,ifconfig、配置文件)

    1.Linux配置IP 地址 ifconfig命令临时配置IP 地址 ifconfig命令,最常用的功能是查看本机的网络的配置状态(当然也可以配置网络,不过是暂时性的),直接输入ifconfig命令就 ...

  10. AgileEAS.NET SOA 中间件平台5.2版本下载、配置学习(四):开源的Silverlight运行容器的编译、配置

    一.前言 AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速开发应用平台.用于帮助中小型软件企业建立一条适合市 ...