1. package com.whw.sortPractice;
  2.  
  3. import java.util.Arrays;
  4.  
  5. public class Sort
  6. {
  7. /**
  8. * 遍历一个数组
  9. * @param sortArray
  10. */
  11. public void outputArray(int[] sortArray)
  12. {
  13. for(int i = 0;i < sortArray.length;i++)
  14. {
  15. System.out.print(sortArray[i] + " ");
  16. }
  17. System.out.println();
  18. }
  19.  
  20. // **********************************插入排序**********************************
  21.  
  22. /**
  23. * 插入排序
  24. * 排序的基本思想是把待排元素前面的元素当做是一个有序列表 把待排元素后面的元素当做一个无序列表
  25. * 只要把待排元素插入到前面的有序列表中某个位置即可
  26. * 待排元素从数组中的第二个数开始到数组中的最后一个数结束
  27. *
  28. * 插入排序的效率非常低 因为一次只能将数据移动一位
  29. * @param sortArray
  30. */
  31. public void insertSort(int[] sortArray)
  32. {
  33. // 这里的i记录的是对数组中的第几个元素进行排序
  34. for(int i = 1;i < sortArray.length;i++)
  35. {
  36. // 把待排元素放到临时变量里面
  37. int tem = sortArray[i];
  38. // j保存的是待排元素最后去的位置的前一个位置
  39. int j = 0;
  40. for(j = i - 1;(j >= 0) && (sortArray[j] > tem);j--)
  41. {
  42. sortArray[j+1] = sortArray[j];
  43. }
  44. sortArray[j+1] = tem;
  45. }
  46. // 输出结果
  47. outputArray(sortArray);
  48. }
  49.  
  50. /**
  51. * shell排序是快速排序的改良版
  52. * shell排序先将要排序的序列切割成多个组 然后在每个组内再使用插入排序
  53. * @param sortArray 待排序的数组
  54. */
  55. public void shellSort(int[] sortArray)
  56. {
  57. // 用这个数组里面的数去依次切割待排序的数组
  58. int[] increArray = new int[]{5,4,3,2};
  59. // 使用增量数组里面的增量依次排序
  60. for(int i = 0;i < increArray.length;i++)
  61. {
  62. // 使用每一个增量进行插入排序 循环一开始 j就定位到了子数组中的第二个元素
  63. for(int j = i + increArray[i];j < sortArray.length;j += increArray[i])
  64. {
  65. // 保存待排序元素的临时变量
  66. int tem = sortArray[j];
  67. int k = j - increArray[i];
  68. for(k = j - increArray[i];(k >= 0) && (sortArray[k] > tem);k -= increArray[i])
  69. {
  70. sortArray[k + increArray[i]] = sortArray[k];
  71. }
  72. k += increArray[i];
  73. sortArray[k] = tem;
  74. }
  75. System.out.println("第" + (i+1) + "趟排序完成 开始遍历数组元素");
  76. outputArray(sortArray);
  77. }
  78. System.out.println("shell排序完成,开始插入排序");
  79. insertSort(sortArray);
  80. }
  81.  
  82. // *************************************选择排序*******************************
  83.  
  84. /**
  85. * 选择排序的基本思想是 每次都选择出从第i到最后一个元素中最小(大)的那一个与第i个元素交换位置
  86. * @param sortArray
  87. */
  88. public void selectSort(int[] sortArray)
  89. {
  90. // 外层循环n-1次
  91. for(int i = 0;i < sortArray.length - 1;i++)
  92. {
  93. // 找出第i个到最后的元素中最小的那个元素
  94. // 最小的元素
  95. int min = sortArray[i];
  96. // 最小元素出现的位置
  97. int pos = i;
  98. for(int j = i;j < sortArray.length;j++)
  99. {
  100. if(sortArray[j] < min)
  101. {
  102. min = sortArray[j];
  103. pos = j;
  104. }
  105. }
  106. if(i != pos)
  107. {
  108. // 把最小元素和第i个元素交换位置
  109. sortArray[pos] = sortArray[i];
  110. sortArray[i] = min;
  111. }
  112. }
  113. }
  114.  
  115. /**
  116. * 二元选择排序 每趟排序中选出最大值和最小值 然后分别把这个最大值和最小值放到参与排序的元素的最左端和最右端
  117. * 总共循环[n/2](下取整)次
  118. * @param sortArray
  119. */
  120. public void twoEleSelectSort(int[] sortArray)
  121. {
  122. // 循环次数
  123. int cycleTime = sortArray.length / 2;
  124. for(int i = 0;i < cycleTime;i++)
  125. {
  126. // 记录最大最小数以及他们出现的位置
  127. int min = sortArray[i];
  128. int minPos = i;
  129. int max = sortArray[i];
  130. int maxPos = i;
  131. // 找出待排元素的最大值和最小值
  132. for(int j = i;j < sortArray.length - i;j++)
  133. {
  134. if(sortArray[j] < min)
  135. {
  136. min = sortArray[j];
  137. minPos = j;
  138. }
  139. if(sortArray[j] > max)
  140. {
  141. max = sortArray[j];
  142. maxPos = j;
  143. }
  144. }
  145. // 把最大值和最小值分别放到待排元素的最左端和最右端
  146. sortArray[minPos] = sortArray[i];
  147. sortArray[i] = min;
  148. sortArray[maxPos] = sortArray[sortArray.length - i - 1];
  149. sortArray[sortArray.length - i - 1] = max;
  150. }
  151. }
  152.  
  153. /**
  154. * 堆排序 可以把一个数组逻辑化成一棵二叉堆 父节点的值大于任一子节点的值时是大根堆 父节点的值小于任一子节点的值是小根堆
  155. * 大根堆的根节点就是当前数组中最大的元素 然后把这个最大的元素和待排元素中最后一个元素交换位置即可
  156. * 排序的过程就是 建树->交换 这个过程循环往复
  157. * 相当于每次通过建树的方式找出待排元素中最大值的那个元素
  158. * @param sortArray
  159. */
  160. /**
  161. * @param sortArray
  162. */
  163. public void heapSort(int[] sortArray)
  164. {
  165. // 建树 父节点和子节点元素数组下标之间的关系为 父节点的下标是i 左子节点的下标是2*i+1 右子节点的下标是2*i+2
  166. // 建树的基本思路是 从最后一个父节点开始保证每个父节点要比左右孩子节点的值大
  167. // 所以要找到最后一个父节点然后不停的和左右孩子节点进行比较和交换
  168. // 通过这样不停的比较和交换最终能保证 sortArray[0]一定是数组元素中的最大值
  169.  
  170. // 最外层的循环指定了要对哪些元素进行建树
  171. int arrLength = sortArray.length;
  172. for(int i = arrLength - 1; i >= 0;i--)
  173. {
  174. // 建树 从给定元素的最后一个开始
  175. for(int j = i; j >= 0;j--)
  176. {
  177. // 判断左子节点是否存在
  178. if(2 * j + 1 >= arrLength || 2 * j + 1 > i)
  179. {
  180. continue;
  181. }
  182. // 如果比左子节点要小就要和左子节点交换
  183. if(sortArray[j] < sortArray[2*j+1])
  184. {
  185. int tem = 0;
  186. tem = sortArray[j];
  187. sortArray[j] = sortArray[2*j+1];
  188. sortArray[2*j+1] = tem;
  189. }
  190. // 判断右子节点是否存在
  191. if(2 * j + 2 >= arrLength || 2 * j + 2 > i)
  192. {
  193. continue;
  194. }
  195. // 如果比右子节点要小就要和右子节点交换
  196. if(sortArray[j] < sortArray[2*j+2])
  197. {
  198. int tem = 0;
  199. tem = sortArray[j];
  200. sortArray[j] = sortArray[2*j+2];
  201. sortArray[2*j+2] = tem;
  202. }
  203. }
  204. // 建树完成 这个时候的sortArray[0]就是待排元素中值最大的那个
  205. int tem = 0;
  206. tem = sortArray[0];
  207. sortArray[0] = sortArray[i];
  208. sortArray[i] = tem;
  209. outputArray(sortArray);
  210. }
  211. }
  212.  
  213. // ****************************************交换排序****************************
  214.  
  215. /**
  216. * 冒泡排序 每次都从数组中的第一个元素开始 每次都把待排元素中的最大的那个沉到最后一个
  217. * 每次比较相邻的两个元素 如果后面的比前面的小就交换
  218. * @param sortArray
  219. */
  220. public void bubbleSort(int[] sortArray)
  221. {
  222. // 外层循环控制待排元素的终点
  223. int endPostion = sortArray.length - 1;
  224. for(int i = endPostion;i >= 0;i--)
  225. {
  226. // 挨个比较待排元素中相邻的元素
  227. for(int j = 0;j < i;j++)
  228. {
  229. if(sortArray[j] > sortArray[j+1])
  230. {
  231. int tem = 0;
  232. tem = sortArray[j];
  233. sortArray[j] = sortArray[j+1];
  234. sortArray[j+1] = tem;
  235. }
  236. }
  237. }
  238. }
  239.  
  240. /**
  241. * 冒泡算法改进版
  242. * 在每一趟排序中增加一个boolean类型的变量 标识这一趟排序中是否有交换发生 如果没有交换发生说明数组已经是有序的
  243. * @param sortArray
  244. */
  245. public void bubbleSortAdvanced(int[] sortArray)
  246. {
  247. // 外层循环控制待排元素的终点
  248. int endPosition = sortArray.length - 1;
  249. boolean isChange = true;
  250. for(int i = endPosition;i >= 0;i--)
  251. {
  252. if(isChange == false)
  253. {
  254. return;
  255. }
  256. isChange = false;
  257. for(int j = 0;j < i;j++)
  258. {
  259. if(sortArray[j] > sortArray[j+1])
  260. {
  261. int tem = sortArray[j];
  262. sortArray[j] = sortArray[j+1];
  263. sortArray[j+1] = tem;
  264. // 修改交换标识符
  265. isChange = true;
  266. }
  267. }
  268. }
  269. }
  270.  
  271. /**
  272. * 双元素冒泡排序算法 每一趟排序中都把最大的元素沉到待排元素的最右端 把最小元素沉到待排元素的最左端
  273. * @param sortArray
  274. */
  275. public void twoElementBubbleSort(int[] sortArray)
  276. {
  277. // 外层循环控制待排元素的终点
  278. int endPosition = sortArray.length - 1;
  279. boolean isChange = true;
  280. for(int i = endPosition;i >= 0;i--)
  281. {
  282. if(isChange == false)
  283. {
  284. return;
  285. }
  286. isChange = false;
  287. // 把最大的元素沉下去
  288. for(int j = 0;j < i;j++)
  289. {
  290. if(sortArray[j] > sortArray[j+1])
  291. {
  292. int tem = sortArray[j];
  293. sortArray[j] = sortArray[j+1];
  294. sortArray[j+1] = tem;
  295. // 修改交换标识符
  296. isChange = true;
  297. }
  298. }
  299. // 把最小的元素浮上来
  300. for(int j = i;j > 0;j--)
  301. {
  302. if(sortArray[j] < sortArray[j-1])
  303. {
  304. int tem = sortArray[j - 1];
  305. sortArray[j - 1] = sortArray[j];
  306. sortArray[j] = tem;
  307. isChange = true;
  308. }
  309. }
  310. }
  311. }
  312.  
  313. /**
  314. * 快速排序 快速排序的规则如下
  315. * 1、设置两个变量i、j初始化的时候i= j=sortArray.length-1 也就是说这两个指针初始化的时候一个指向第一个待排元素 一个指向最后一个待排元素
  316. * 2、每次把待排元素的第一个当做关键数据赋值给key 即key=sortArray[0]
  317. * 3、j向前移动 找到第一个比key小的元素sortArray[j] 让sortArray[j]和sortArray[i]交换
  318. * 4、i向后移动 找到第一个比key大的元素sortArray[i] 让sortArray[i]和sortArray[j]交换
  319. * 5、重复3到4 直到i和j相等
  320. * 注意:快速排序中需要注意的地方有两个
  321. * 1、只有sortArray[i]小于等于key的时候i才向前移动 或 sortArray[j]大于等于key的时候j才向后移动
  322. * 2、根据注意的第一点 如果sortArray[i]和sortArray[j]交换 i j 这两个指针都不移动
  323. *
  324. * 经过一趟排序之后数组就变成了key左边的元素都不大于key key右边的元素都不小于key
  325. * 只要对key左右两侧的子数组进行递归排序即可
  326. * @param sortArray
  327. */
  328. public void quickSort(int[] sortArray,int startIndex,int endIndex)
  329. {
  330. // 递归终止条件
  331. if(startIndex >= endIndex)
  332. {
  333. return;
  334. }
  335. // 第一趟排序
  336. int i = startIndex;
  337. int j = endIndex;
  338. int key = sortArray[i];
  339. // 当两个指针没有相遇的时候循环要一直持续
  340. // 这个循环结束的时候i和j已经相等
  341. outer:while(i < j)
  342. {
  343. System.out.println(key);
  344. // sortArray[j]比key要大指针就一直向前移动
  345. while(sortArray[j] >= key)
  346. {
  347. System.out.println(sortArray[j] + " " + key);
  348. j--;
  349. // 这里也是一个需要注意的地方 如果j和i已经相等了就要结束外层循环
  350. if(i == j)
  351. {
  352. break outer;
  353. }
  354.  
  355. }
  356. if(i < j)
  357. // sortArray[j]小于key的时候交换sortArray[i]和sortArray[j]
  358. System.out.println("右侧交换" + sortArray[i] + " " + sortArray[j]);
  359. int tem = sortArray[i];
  360. sortArray[i] = sortArray[j];
  361. sortArray[j] = tem;
  362. outputArray(sortArray);
  363. System.out.println("右侧交换完成");
  364. // sortArray[i]比key要小指针就一直向后移动
  365. while(sortArray[i] <= key && j > i)
  366. {
  367. i++;
  368. if(i == j)
  369. {
  370. break outer;
  371. }
  372. }
  373. // sortArray[i]大于key的时候交换sortArray[i]和sortArray[j]
  374. System.out.println("左侧交换" + sortArray[i] + " " + sortArray[j]);
  375. tem = sortArray[i];
  376. sortArray[i] = sortArray[j];
  377. sortArray[j] = tem;
  378. outputArray(sortArray);
  379. System.out.println("左侧交换完成");
  380. }
  381. outputArray(sortArray);
  382. System.out.println("一次排序结束");
  383. // 递归key左边的部分
  384. quickSort(sortArray, startIndex, i-1);
  385. // 递归key右边的部分
  386. quickSort(sortArray, i+1,endIndex);
  387. }
  388.  
  389. /**
  390. * 归并排序
  391. * 归并排序的思路不算复杂 主要是递归 合并
  392. * 先把待排数组从中间分开然后对左右两个子数组进行递归 直到子数组被划分为只有两个元素 对这两个元素进行递归之后然后合并 在这个合并的过程中两个元素发生了交换
  393. * 首先要理解递归的过程 其次要理解合并
  394. * 现在对这个算法还不是很理解
  395. * @param sortArray
  396. */
  397. public void mergeSort(int[] sortArray,int low,int high)
  398. {
  399. // 这一步就是在不停的拆分数组
  400. int mid = (low + high) / 2;
  401. if(low < high)
  402. {
  403. // 通过左右两侧的递归就能保证左右两侧的子数组全部有序
  404. // 递归执行左边的部分
  405. mergeSort(sortArray, low, mid);
  406. // 递归执行右边的部分
  407. mergeSort(sortArray, mid + 1, high);
  408.  
  409. System.out.println("左右递归完成 测试左右数组是否有序");
  410. for(int i = low;i <= mid;i++)
  411. {
  412. System.out.print(sortArray[i] + " ");
  413. }
  414. System.out.print("--------");
  415. for(int i = mid+1;i <= high;i++)
  416. {
  417. System.out.print(sortArray[i] + " ");
  418. }
  419. System.out.println();
  420.  
  421. // 左右数组已经有序 可以进行交换
  422. // 先把sortArray中的元素放到tem中 然后把tem中的元素赋值给sortArray中
  423. // 这里的数组长度开辟出错 调了很长时间才调出来
  424. int[] tem = new int[high - low + 1];
  425. // 分别指向左右两侧数组第一个元素的指针
  426. int leftIndex = low;
  427. int rightIndex = mid + 1;
  428. // 标识tem的指针
  429. int temIndex = 0;
  430. while(leftIndex <= mid && rightIndex <= high)
  431. {
  432. if(sortArray[leftIndex] < sortArray[rightIndex])
  433. {
  434. tem[temIndex] = sortArray[leftIndex];
  435. leftIndex++;
  436. }
  437. else
  438. {
  439. tem[temIndex] = sortArray[rightIndex];
  440. rightIndex++;
  441. }
  442. temIndex++;
  443. }
  444. System.out.println("全部移出");
  445. System.out.println("tem[]中的元素为" + Arrays.toString(tem));
  446. outputArray(sortArray);
  447.  
  448. while(leftIndex <= mid)
  449. {
  450. tem[temIndex] = sortArray[leftIndex];
  451. leftIndex++;
  452. temIndex++;
  453. }
  454.  
  455. while(rightIndex <= high)
  456. {
  457. tem[temIndex] = sortArray[rightIndex];
  458. rightIndex++;
  459. temIndex++;
  460. }
  461.  
  462. for(int i = 0;i < tem.length;i++)
  463. {
  464. sortArray[low+i] = tem[i];
  465. }
  466. // 把tem中的前temIndex-1个移动到sortArray中 从low开始向后temIndex-1个位置上面去
  467. /*int temIndex2 = 0;
  468. int sortIndex = low;
  469. while(temIndex2 <= temIndex-1)
  470. {
  471. sortArray[sortIndex] = tem[temIndex2];
  472. temIndex2++;
  473. sortIndex++;
  474. }*/
  475. System.out.println("重新移入");
  476. outputArray(sortArray);
  477. }
  478. }
  479.  
  480. public static void main(String[] args)
  481. {
  482. // 测试数组 {9,8,7,5,1,2,3,12,3,5,88,99,78,90,78,66,543,77,54,9,3,21,125}
  483. int[] sortArray = new int[] {9,8,7,5,1,2,3,12,3,5,88,99,78,90,78,66,543,77,54,9,3,21,125};
  484. Sort test = new Sort();
  485. // test.insertSort(sortArray);
  486. // test.shellSort(sortArray);
  487. // test.selectSort(sortArray);
  488. // test.twoEleSelectSort(sortArray);
  489. // test.heapSort(sortArray);
  490. // test.bubbleSort(sortArray);
  491. // test.bubbleSortAdvanced(sortArray);
  492. // test.twoElementBubbleSort(sortArray);
  493. // test.quickSort(sortArray, 0, sortArray.length-1);
  494. test.mergeSort(sortArray, 0, sortArray.length-1);
  495. test.outputArray(sortArray);
  496. }
  497. }

  

常用排序算法--java版的更多相关文章

  1. 常用排序算法java实现

    写在前面:纸上得来终觉浅.基本排序算法的思想,可能很多人都说的头头是到,但能说和能写出来,真的还是有很大区别的. 今天整理了一下各种常用排序算法,当然还不全,后面会继续补充.代码中可能有累赘或错误的地 ...

  2. 排序算法Java版,以及各自的复杂度,以及由堆排序产生的top K问题

    常用的排序算法包括: 冒泡排序:每次在无序队列里将相邻两个数依次进行比较,将小数调换到前面, 逐次比较,直至将最大的数移到最后.最将剩下的N-1个数继续比较,将次大数移至倒数第二.依此规律,直至比较结 ...

  3. 排序算法系列:选择排序算法JAVA版(靠谱、清晰、真实、可用、不罗嗦版)

    在网上搜索算法的博客,发现一个比较悲剧的现象非常普遍: 原理讲不清,混乱 啰嗦 图和文对不上 不可用,甚至代码还出错 我总结一个清晰不罗嗦版: 原理: 从数组头元素索引i开始,寻找后面最小的值(比i位 ...

  4. 排序算法Java版

    选择排序: public static void selectSort(int[]a) { int minIndex=0; int temp=0; if((a==null)||(a.length==0 ...

  5. 我们一起来排序——使用Java语言优雅地实现常用排序算法

    破阵子·春景 燕子来时新社,梨花落后清明. 池上碧苔三四点,叶底黄鹂一两声.日长飞絮轻. 巧笑同桌伙伴,上学径里逢迎. 疑怪昨宵春梦好,元是今朝Offer拿.笑从双脸生. 排序算法--最基础的算法,互 ...

  6. Java常用排序算法+程序员必须掌握的8大排序算法+二分法查找法

    Java 常用排序算法/程序员必须掌握的 8大排序算法 本文由网络资料整理转载而来,如有问题,欢迎指正! 分类: 1)插入排序(直接插入排序.希尔排序) 2)交换排序(冒泡排序.快速排序) 3)选择排 ...

  7. Java 常用排序算法/程序员必须掌握的 8大排序算法

    Java 常用排序算法/程序员必须掌握的 8大排序算法 分类: 1)插入排序(直接插入排序.希尔排序) 2)交换排序(冒泡排序.快速排序) 3)选择排序(直接选择排序.堆排序) 4)归并排序 5)分配 ...

  8. Java常用排序算法及性能测试集合

    测试报告: Array length: 20000 bubbleSort : 573 ms bubbleSortAdvanced : 596 ms bubbleSortAdvanced2 : 583 ...

  9. 常用排序算法的总结以及编码(Java实现)

    常用排序算法的总结以及编码(Java实现) 本篇主要是总结了常用算法的思路以及相应的编码实现,供复习的时候使用.如果需要深入进行学习,可以使用以下两个网站: GeeksForGeeks网站用于学习相应 ...

随机推荐

  1. Canvas路径方向

    使用Canvas路径画图需要注意方向,画图方向是顺时针还是逆时针需要记住.下面让我们看看Canvas常见路径方向. arc 参数值 context.arc(x,y,r,sAngle,eAngle,co ...

  2. Java : logback简单配置

    需要把logback.xml文件放在类路径下,如果是spring boot项目可以用 logging.config=classpath:log/xxxxxx.xml来指定配置文件 logback la ...

  3. 3D立方体

    效果图 主要用到的3D属性 1.保留子元素的3d属性:transform-style:preserve-3d; 2.2D变形属性: ①transform:translate()平移,分X轴,Y轴,Z轴 ...

  4. 手搓一个C语言简单计算器。

    #include <stdio.h> void xing(int shu); void biaoti(int kong,char * title); void zhuyemian(char ...

  5. struts2学习笔记二

    一.分文件编写框架配置文件 1.不分文件开发可能产生的问题 就类似于我们在写java类时,所有代码都写在一个类里,甚至写在一个方法里. 当3个人都checkout了struts.xml文件时,第一个人 ...

  6. 状压搜索 洛谷T47092 作业

    TYM 有 nn 本作业,编号为 1,\dots,n1,…,n. 由于 \mathrm{TYM}TYM 很喜欢偷懒,而且不喜欢消耗脑细胞,所以他选择跳着完成这 nn 本作业.此外,如果将做作业的顺序转 ...

  7. sphinx生成cakephp文档

    cakephp的文档是用一个叫sphinx程序生成的 这个程序是python写的,所以我们要用sphinx本机必须先装python. 编译过程在Ubuntu下进行,默认Ubuntu已经安装了pytho ...

  8. Qt-QPalette-调色板学习

    已经很久没有更新博客了,一是因为换了公司,完全是断网开发了,没有时间来写博客,最主要的就是温水煮青蛙,自己在舒适的环境中越来越懒了,最近打算强制自己更新一波.不知道能坚持多久.由于目前没有具体的Qt项 ...

  9. 为什么测试人员必须掌握Linux?

    相信点进来的小伙伴不是对Linux感兴趣就是对测试感兴趣了,也希望本文可以帮助之前接触过Linux的小伙伴找到继续坚持学习下去的动力,之前没接触过Linux的小伙伴也能找到开始学习Linux的兴趣. ...

  10. Linux命令应用大词典-第2章 获取帮助

    2.1 help:查看内部Shell命令帮助信息 2.2 man:显示在线手册页 2.3 manpath:查看和设置man手册页的查询路径 2.4 info:阅读info格式的文件 2.5 pinfo ...