排序算法总结java

灰太狼 2022-05-08 20:57 204阅读 0赞

难易程度:★

重要性:★★★★★

包含了:链表的快速排序和链表的归并排序

  1. package com.sort;
  2. import java.util.Arrays;
  3. public class SortSummarize {
  4. public static void main(String[] args) {
  5. int[] a = {9,8,7,6,5,1,3,0,10,-1,99,-10};
  6. int[] b = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,17,16};
  7. b = a;
  8. print("选择排序 ",selectSort(b));
  9. print("冒泡排序 ",bubbleSort(b));
  10. print("插入排序 ",insertSort(b));
  11. print("归并排序 ",mergeSort(b));
  12. print("希尔排序 ",shellSort(b));
  13. print("堆排序 ",heapSort(b));
  14. print("快速排序 ",quickSort(b));
  15. }
  16. /**
  17. * 冒泡排序算法:每次将最小的一个数”浮“上去
  18. * 最好情况O(n),即数组本身有序
  19. * 最坏情况O(n^2)
  20. */
  21. public static int[] bubbleSort(int[] a) {
  22. a = Arrays.copyOf(a, a.length);
  23. int count = 0;
  24. boolean terminated = false;
  25. for(int i=0;i<a.length-1&&!terminated;i++) {
  26. terminated = true;
  27. for(int j=a.length-2;j>=i;j--) {
  28. count++;
  29. if(a[j]>a[j+1]) {
  30. swap(a,j+1,j);
  31. terminated = false;
  32. }
  33. }
  34. }
  35. System.out.println("冒泡排序比较次数: "+count);
  36. return a;
  37. }
  38. /**
  39. * 选择排序:每次选出待排序中最小的一个
  40. */
  41. public static int[] selectSort(int[] a) {
  42. a = Arrays.copyOf(a, a.length);
  43. int count = 0;
  44. for(int i=0;i<a.length-1;i++) {
  45. int min = a[i];
  46. int minIndex = i;
  47. for(int j=i+1;j<a.length;j++) {
  48. count++;
  49. if(a[j]<min) {
  50. minIndex = j;
  51. min = a[j];
  52. }
  53. }
  54. swap(a,i,minIndex);
  55. }
  56. System.out.println("选择排序比较次数: "+count);
  57. return a;
  58. }
  59. public static int[] insertSort(int[] a) {
  60. a = Arrays.copyOf(a, a.length);
  61. int count = 0;
  62. for(int i=1;i<a.length;i++) {// i之前有序,i指向待排序的元素
  63. if(a[i]<a[i-1]) {
  64. int temp = a[i];
  65. int j = i-1;//j指向当前元素的前一个
  66. for(;j>=0&&a[j]>temp;j--) {
  67. count++;
  68. a[j+1] = a[j];
  69. }
  70. a[j+1] = temp;
  71. }
  72. }
  73. System.out.println("插入排序比较次数: "+count);
  74. return a;
  75. }
  76. private static void swap(int[] a,int i,int j) {
  77. if (i==j) return;
  78. int temp = a[i];
  79. a[i] = a[j];
  80. a[j] = temp;
  81. }
  82. /**
  83. * 希尔排序
  84. * @param a
  85. * @return
  86. */
  87. public static int[] shellSort(int[] a) {
  88. a = Arrays.copyOf(a, a.length);
  89. int count = 0;
  90. int increment = a.length;
  91. do {
  92. increment = increment/3 + 1;
  93. for(int i=increment;i<a.length;i=i+increment) {
  94. if(a[i]<a[i-increment]) {
  95. int temp = a[i];
  96. int j=i-increment;
  97. for(;j>=0&&a[j]>temp;j -= increment) {
  98. count++;
  99. a[j+increment] = a[j];
  100. }
  101. a[j+increment] = temp;
  102. }
  103. }
  104. }while(increment>1);
  105. System.out.println("希尔排序比较次数: "+count);
  106. return a;
  107. }
  108. /**
  109. * 堆排序
  110. * @param a
  111. * @return
  112. */
  113. public static int[] heapSort(int[] a) {
  114. a = Arrays.copyOf(a, a.length);
  115. int length = a.length;
  116. for(int i=length/2-1;i>=0;i--)//2*i+1<=length-1,最后一个有左孩子的节点
  117. heapAdjust(a,i,length);
  118. for(int i=length-1;i>=0;i--) {
  119. swap(a,0,i);
  120. heapAdjust(a,0,i);//
  121. }
  122. return a;
  123. }
  124. //每次将以i为root的子树满足最大堆特性;i指向待调整的节点
  125. private static void heapAdjust(int[] a,int i,int length) {
  126. int temp = a[i];
  127. for(int j=2*i+1;j<length;j=2*i+1){//刚开始时指向左孩子
  128. if(j+1<length && a[j+1]>a[j])//如果有做右孩子,且右孩子比左孩子大
  129. j++;//j指向左右孩子中值较大的一个
  130. if(temp>=a[j])
  131. break;
  132. a[i] = a[j];
  133. i=j;
  134. }
  135. a[i] = temp;
  136. }
  137. public static int[] mergeSort(int[] a) {
  138. a = Arrays.copyOf(a, a.length);
  139. int[] aux = new int[a.length];
  140. mergeSort(a,aux,0,a.length-1);
  141. return a;
  142. }
  143. private static void mergeSort(int[] a,int[] aux,int lo,int high) {
  144. if(lo>=high) return;
  145. int mid = (lo+high)/2;
  146. mergeSort(a,aux,lo,mid);
  147. mergeSort(a,aux,mid+1,high);
  148. merge(a,aux,lo,mid,high);
  149. }
  150. private static void merge(int[] a,int aux[],int lo,int mid,int high) {
  151. for(int i=lo;i<=high;i++) {
  152. aux[i] = a[i];
  153. }
  154. int lo_h = mid+1;
  155. for(int i=lo;i<=high;i++) {
  156. if(lo>mid)
  157. a[i] = aux[lo_h++];
  158. else if(lo_h>high)
  159. a[i] = aux[lo++];
  160. else {
  161. if(aux[lo]<=aux[lo_h])
  162. a[i] = aux[lo++];
  163. else
  164. a[i] = aux[lo_h++];
  165. }
  166. }
  167. }
  168. /**
  169. * 快速排序
  170. * @param a
  171. * @return
  172. */
  173. public static int[] quickSort(int[] a) {
  174. a = Arrays.copyOf(a, a.length);
  175. quickSort(a,0,a.length-1);
  176. return a;
  177. }
  178. private static void quickSort(int[] a,int low,int high) {
  179. if(low>=high) return;
  180. int partition = partition(a,low,high);
  181. quickSort(a,low,partition-1);
  182. quickSort(a,partition+1,high);
  183. }
  184. private static int partition(int[] a,int low,int high) {
  185. int tempt = a[low];
  186. while(low<high) {
  187. while(low<high&&a[high]>=tempt)
  188. high--;
  189. // swap(a,low,high);
  190. a[low] = a[high];
  191. while(low<high&&a[low]<=tempt)
  192. low++;
  193. // swap(a,low,high);
  194. a[high] = a[low];
  195. }
  196. a[low] = tempt;
  197. return low;
  198. }
  199. private static void print(String str,int[] a) {
  200. System.out.println(str);
  201. for(int i=0;i<a.length;i++)
  202. System.out.print(a[i]+" ");
  203. System.out.println("\n");
  204. }
  205. /**
  206. * 下面是链表的快速排序
  207. * @param str
  208. * @param a
  209. */
  210. public static ListNode quickSort(ListNode begin, ListNode end) {
  211. //判断为空,判断是不是只有一个节点
  212. if (begin == null || end == null || begin == end)
  213. return begin;
  214. //从第一个节点和第一个节点的后面一个几点
  215. //begin指向的是当前遍历到的最后一个<= nMidValue的节点
  216. ListNode first = begin;
  217. ListNode second = begin.next;
  218. int nMidValue = begin.val;
  219. //结束条件,second到最后了
  220. while (second != end.next && second != null) {//结束条件
  221. //一直往后寻找<=nMidValue的节点,然后与fir的后继节点交换
  222. if (second.val < nMidValue) {
  223. first = first.next;
  224. //判断一下,避免后面的数比第一个数小,不用换的局面
  225. if (first != second) {
  226. int temp = first.val;
  227. first.val = second.val;
  228. second.val = temp;
  229. }
  230. }
  231. second = second.next;
  232. }
  233. //判断,有些情况是不用换的,提升性能
  234. if (begin != first) {
  235. int temp = begin.val;
  236. begin.val = first.val;
  237. first.val = temp;
  238. }
  239. //前部分递归
  240. quickSort(begin, first);
  241. //后部分递归
  242. quickSort(first.next, end);
  243. return begin;
  244. }
  245. /**
  246. * 链表的归并排序
  247. */
  248. public ListNode sortList1(ListNode head) {
  249. if(head==null||head.next==null) return head;
  250. quickSort(null,null);
  251. return mergeSort(head);
  252. }
  253. private ListNode mergeSort(ListNode head){
  254. if(head==null || head.next==null) return head;
  255. ListNode mid = getMid(head);
  256. ListNode second = mid.next;
  257. mid.next = null;
  258. ListNode left = mergeSort(head);
  259. ListNode right = mergeSort(second);
  260. return merge(right,left);
  261. }
  262. private ListNode merge(ListNode l1,ListNode l2){
  263. ListNode dummy = new ListNode(0);
  264. ListNode cur = dummy;
  265. while(l1!=null&&l2!=null){
  266. if(l1.val<=l2.val){
  267. cur.next = l1;
  268. l1 = l1.next;
  269. }else{
  270. cur.next = l2;
  271. l2 = l2.next;
  272. }
  273. cur = cur.next;
  274. }
  275. if(l1!=null)
  276. cur.next = l1;
  277. else
  278. cur.next = l2;
  279. return dummy.next;
  280. }
  281. private ListNode getMid(ListNode head){
  282. if(head==null ||head.next==null) return head;
  283. ListNode slow = head;
  284. ListNode faster = head.next;
  285. while(faster!=null&&faster.next!=null){
  286. slow = slow.next;
  287. faster = faster.next.next;
  288. }
  289. return slow;
  290. }
  291. }

在理解的基础上掌握上述算法的实现,其中快速排序、归并排序、堆排序和链表的排序是重点中的重点,要求三分钟内可以正确手写实现任何一种排序算法,以及对应的复杂度、稳定性等特征。算法稳定性的考察也是面试中的另外一个重点,在理解的基础上,牢记下表:

70


扫描下方二维码,及时获取更多互联网求职面经javapython爬虫大数据等技术,和海量资料分享
公众号菜鸟名企梦后台发送“csdn”即可免费领取【csdn】和【百度文库】下载服务;
公众号菜鸟名企梦后台发送“资料”:即可领取5T精品学习资料java面试考点java面经总结,以及几十个java、大数据项目资料很全,你想找的几乎都有

扫码关注,及时获取更多精彩内容。(博主今日头条大数据工程师)

扫码关注,及时获取更多精彩内容。(博主今日头条大数据工程师)

发表评论

表情:
评论列表 (有 0 条评论,204人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Java排序算法总结

     概述排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。 我们这里说说八

    相关 java排序算法总结

    java 常见的排序算法:冒泡排序,快速排序,选择排序等; 1.冒泡排序:概念--重复的比较要排序的序列,每次比较相邻的两个元素,直到排序完成。        排序步骤如下

    相关 java排序算法总结

    java排序算法总结 排序,这是一个很古老但是又很经典的问题,世界上有很多中优秀排序算法的实现,在这里,我总结了其他比较常用的几种排序算法 1.java排序算法一览