当前位置:   article > 正文

java实现七种经典排序算法_java排序算法

java排序算法

简单算法:冒泡,简单选择,直接插入

改进算法:希尔,堆,归并,快速

直接插入排序:将一个记录插入到已经拍好的有序列表中,从而得到一个新的、记录数增加1的有序表。

冒泡排序:两两比较,反序交换。每趟将最大(小 )的浮到最上面或沉到最底下。

简单选择排序:通过关键字之间的比较,每次将剩余的记录中选择最小的与指定位置交换。

希尔排序:跳跃的插入排序,选择某个增量,对间隔增量的子序列进行排序,随着增量递减,逐步完成所有值的排序。

堆排序:将待排序序列构建成一个大顶堆,此时整个序列最大值就是根节点。将它和末尾元素交换,随后将剩余的n-1个元素重新构造成一个堆,以此类推。

归并排序:拆分,随后重组。

快速排序:通过一趟排序将待排记录分成独立的两部分,一部分都小于另一部分,随后对两部分分别进行再次排序,以达到整体有序。

(所有代码均可独立运行成功)


冒泡排序:

  1. import java.util.Arrays;
  2. /**
  3. * 冒泡排序算法
  4. * 两两比较相邻记录的关键字,如果反序则交换,直到没有反序记录为止
  5. * @author 诸葛浪
  6. *
  7. */
  8. public class BubbleSortDemo {
  9. public static void bubbleSort0(int[] arr) {
  10. //初级版本冒泡算法 每一个关键字都和后面每一个关键字相比较
  11. for(int i =0;i<arr.length-1;i++)
  12. for(int j =i+1; j<arr.length;j++)
  13. if(arr[i] > arr[j])
  14. swap(arr, i, j);
  15. }
  16. public static void bubbleSort(int[] arr) {
  17. //从后往前 两两比较 每一轮把最小的转移到i的位置
  18. for(int i=0;i<arr.length;i++)
  19. for(int j = arr.length-1;j>i;j--)//for(int j=0 ; j<arr.length-1-i ; j++) 从前往后也可以 每一趟把最大的放最后
  20. if(arr[j-1] > arr[j])
  21. swap(arr, j-1, j);
  22. }
  23. public static void bubbleSort2(int[] arr) {
  24. //改进版 如果一趟下来没有交换 说明有序 之后就不必循环判断了
  25. boolean flag = true;//用以记录是否发生交换
  26. for(int i = 0;i<arr.length&&flag;i++) {
  27. flag = false;
  28. for(int j = arr.length - 1;j>i;j--) {
  29. if(arr[j-1] > arr[j]) {
  30. swap(arr, j-1, j);
  31. flag = true;
  32. }
  33. }
  34. }
  35. }
  36. public static void main(String[] args) {
  37. int[] arrTest = {9,1,5,8,3,7,4,6,2};
  38. System.out.println("before: " + Arrays.toString(arrTest));
  39. bubbleSort2(arrTest);
  40. System.out.println("after: " + Arrays.toString(arrTest));
  41. }
  42. public static void swap(int[] arr , int i, int j) {
  43. //交换数组两元素
  44. int temp = arr[i];
  45. arr[i] = arr[j];
  46. arr[j] = temp;
  47. }
  48. }

 

直接插入排序:

  1. import java.util.Arrays;
  2. /**
  3. * 插入排序算法
  4. * 基本操作是将一个记录插入到已经排好序的有序表中,从而得到一个记录数+1的有序表
  5. * @author 诸葛浪
  6. *
  7. */
  8. public class InsertSortDemo {
  9. public static void insertSort(int[] arr) {
  10. //设置一个辅助空间arr[0]
  11. for(int i =2;i<arr.length;i++ ) {
  12. if(arr[i] < arr[i-1]) { //需要将arr[i]插入有序子表
  13. arr[0] = arr[i];//设置哨兵
  14. int j;
  15. for(j = i-1;arr[j] > arr[0];j--)
  16. arr[j+1] = arr[j];//记录后移
  17. arr[j+1] = arr[0];//插入到正确位置
  18. }
  19. }
  20. }
  21. public static void main(String[] args) {
  22. int[] arrTest = {0,1,5,8,3,7,4,6,2};
  23. System.out.println("before: " + Arrays.toString(arrTest));
  24. insertSort(arrTest);
  25. System.out.println("after: " + Arrays.toString(arrTest));
  26. }
  27. }

简单选择排序

  1. import java.util.Arrays;
  2. /**
  3. * 简单选择排序
  4. * 基本思想是每一趟在n-i个记录中选择最小的作为第i个记录(从0开始)
  5. *
  6. * @author 诸葛浪
  7. *
  8. */
  9. public class SelectSortDemo {
  10. public static void selectSort(int[] arr) {
  11. //选择排序 每一趟找到最小的放到i的位置
  12. for(int i=0;i<arr.length;i++) {
  13. int min = i;//将当前下标定义为最小值下标
  14. for(int j = i+1; j<arr.length;j++) {
  15. if(arr[min] > arr[j] )//如果有小于当前最小值的关键字
  16. min = j; //将此下标赋值给min
  17. }
  18. if(i != min)//有更改 则交换
  19. swap(arr, i, min);
  20. }
  21. }
  22. public static void main(String[] args) {
  23. int[] arrTest = {9,1,5,8,3,7,4,6,2};
  24. System.out.println("before: " + Arrays.toString(arrTest));
  25. selectSort(arrTest);
  26. System.out.println("after: " + Arrays.toString(arrTest));
  27. }
  28. public static void swap(int[] arr , int i, int j) {
  29. //交换数组两元素
  30. int temp = arr[i];
  31. arr[i] = arr[j];
  32. arr[j] = temp;
  33. }
  34. }

希尔排序:

  1. import java.util.Arrays;
  2. /**
  3. * 希尔排序 又叫增量递减排序
  4. * 将相距某个”增量“的记录组成一个子序列
  5. * 保证在子序列内分别进行直接插入排序后得到的结果是基本有序的
  6. * 直接插入排序的升级版
  7. * @author 诸葛浪
  8. *
  9. */
  10. public class ShellSortDemo {
  11. public static void shellSort(int[] arr) {
  12. //增量递减的插入排序
  13. int increment = arr.length;
  14. do {
  15. increment = increment / 3 + 1;
  16. for(int i = increment + 1 ; i < arr.length; i++) {
  17. if(arr[i] < arr[i - increment]) {//对间隔增量的位置进行比较
  18. arr[0] = arr[i];//暂存在0
  19. int j;
  20. for(j = i - increment; j> 0 && arr[0] < arr[j]; j -= increment)
  21. arr[j+increment] = arr[j];//记录后移 查找插入位置
  22. arr[j+increment] = arr[0];
  23. }
  24. }
  25. }while(increment > 1);
  26. }
  27. public static void main(String[] args) {
  28. int[] arrTest = {0,1,5,8,3,7,4,6,2};
  29. System.out.println("before: " + Arrays.toString(arrTest));
  30. shellSort(arrTest);
  31. System.out.println("after: " + Arrays.toString(arrTest));
  32. }
  33. }

 

堆排序:

  1. import java.util.Arrays;
  2. /**
  3. * 堆排序 利用完全二叉树的结构
  4. * 对于完全二叉树来说,层序遍历之后如果i>1 则i/2(向上取整3.5->3)为其双亲节点
  5. * 而双亲节点均大于或小于子节点
  6. * 根节点最大称大顶堆 否则小顶堆
  7. * 通过不断移除根节点(与末尾结点交换)并重新组织成堆
  8. * 从而得到有序序列
  9. * 简单选择排序的升级版
  10. * @author 诸葛浪
  11. *
  12. */
  13. public class HeapSortDemo {
  14. public static void heapSort(int[] arr) {
  15. for(int i = (arr.length-1)/2; i>0;i--)
  16. heapAdjust(arr, i, arr.length-1);
  17. for(int i = (arr.length-1);i>1;i--) {
  18. swap(arr, 1, i);
  19. heapAdjust(arr, 1, i-1);
  20. }
  21. }
  22. public static void heapAdjust(int[] arr, int s, int m) {
  23. //将s到m调整为大顶堆
  24. int temp = arr[s];
  25. for(int j = s*2;j<=m;j*=2) {//左孩子节点2*s 右孩子2*s+1
  26. if(j < m && arr[j] < arr[j+1])//左孩子小于右孩子 j指向右孩子
  27. ++j;
  28. if(temp >= arr[j])//根节点大于右孩子 满足大顶堆特性 跳出循环
  29. break;
  30. arr[s] = arr[j];//否则将大节点赋值给根节点
  31. s = j;//根节点向下指向孩子节点
  32. }
  33. arr[s] = temp;
  34. }
  35. public static void swap(int[] arr , int first, int next) {
  36. //交换数组两元素
  37. int temp = arr[first];
  38. arr[first] = arr[next];
  39. arr[next] = temp;
  40. }
  41. public static void main(String[] args) {
  42. int[] arrTest = {0,50,10,90,30,70,40,80,60,20};
  43. System.out.println("before: " + Arrays.toString(arrTest));
  44. heapSort(arrTest);
  45. System.out.println("after: " + Arrays.toString(arrTest));
  46. }
  47. }

归并排序:

  1. import java.util.Arrays;
  2. /**
  3. * 归并排序算法
  4. * 假设初始序列含有n个记录 则可以看成是n个有序的子序列 每个子序列长度为1
  5. * 然后两两归并 得到n/2(向上取整)个长度为2或1的有序子序列 两两归并 如此重复
  6. * 直到得到长度为n的有序序列为止 称为2路归并
  7. * 一种拆分到最小 并从最小合并成最大的思路
  8. * 拆分之后的归并实际上是选择排序的一种
  9. * @author 诸葛浪
  10. *
  11. */
  12. public class MergeSortDemo {
  13. public static void mergeSort(int[] arr ) {
  14. mSort(arr, arr, 0, arr.length-1);
  15. }
  16. public static void mSort(int[] SR,int[] TR1,int s, int t ) {
  17. int m;
  18. int[] TR2 = new int[SR.length + 1];
  19. if(s == t)//递归返回条件 拆分至最小了
  20. TR1[s] = SR[s];
  21. else {
  22. m = (s+t)/2; //将SR[s..t]分成s到m和m+1到t
  23. mSort(SR, TR2, s, m); //递归地将SR[s...m]归并为有序的TR2[s..m]
  24. mSort(SR, TR2, m+1, t); //同上
  25. merge(TR2,TR1,s,m,t);//TR2归并到TR1中
  26. }
  27. }
  28. public static void merge(int[] SR,int[] TR,int i, int m ,int n ) {
  29. //将有序的SR[i..m]和SR[m+1...n]归并为有序的TR[i...n]
  30. int j,k,l;
  31. for(j = m+1,k=i;i<=m&&j<=n;k++) {//两半里面挨个挑 将SR中记录由小到大并入TR
  32. if(SR[i] < SR[j])//比较符号反过来就是从大到小的排序
  33. TR[k] = SR[i++];
  34. else
  35. TR[k] = SR[j++];
  36. }
  37. //剩下哪个全都归入TR数组
  38. if(i <= m)
  39. for(l = 0;l<=m-i;l++)
  40. TR[k+l] = SR[i+l];
  41. if(j <= n)
  42. for(l = 0;l<=n-j;l++)
  43. TR[k+l] = SR[j+l];
  44. }
  45. public static void main(String[] args) {
  46. int[] arrTest = {50,10,90,30,70,40,80,60,20};
  47. System.out.println("before: " + Arrays.toString(arrTest));
  48. mergeSort(arrTest);
  49. System.out.println("after: " + Arrays.toString(arrTest));
  50. }
  51. }

快速排序:

  1. import java.util.Arrays;
  2. /**
  3. * 快速排序算法
  4. * 属于交换排序
  5. * 基本思想是通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分小
  6. * 则可以分别对这两个部分继续进行排序 以达到整个序列有序的目的
  7. *
  8. * @author 诸葛浪
  9. *
  10. */
  11. public class QuickSortDemo {
  12. public static void quickSort(int[] arr) {
  13. qSort(arr, 0, arr.length-1);
  14. }
  15. /*对arr中的子序列arr[low...high]做快速排序*/
  16. public static void qSort(int[] arr, int low,int high) {
  17. int pivot;//枢轴变量
  18. if(low < high) {
  19. //将arr[]一分为二 算出枢轴值pivot
  20. //pivot = partition(arr, low ,high);
  21. pivot = partition1(arr, low, high);
  22. qSort(arr, low, pivot-1);//对低子表进行递归排序
  23. qSort(arr, pivot+1, high);//对高子表进行递归排序
  24. }
  25. }
  26. /*交换arr中字表的记录 使枢轴记录到位 并返回其所在位置,此时在它之前均不大于他 之后均不小于他*/
  27. public static int partition(int[] arr, int low, int high) {
  28. int pivotKey = arr[low];//用子表的第一个记录作为枢轴值
  29. while(low < high) {//low和high双指针不断向中间靠拢,枢轴值也在不断移动 性能依赖枢轴值在序列中的分布
  30. //另一个版本中也可以不移动枢轴值 最后赋值皆可
  31. while(low < high && arr[high] >= pivotKey)
  32. high--;
  33. swap(arr, low, high);
  34. while(low < high && arr[low] <= pivotKey)
  35. low++;
  36. swap(arr, low, high);
  37. }
  38. return low;
  39. }
  40. public static int partition1(int[] arr, int low, int high) {
  41. int pivotKey ;//用子表三数取中法 作为枢轴值
  42. int m = low +(high - low) /2;//找到序列中间位置
  43. if(arr[low] > arr[high])
  44. swap(arr, low, high);
  45. if(arr[m] > arr[high])
  46. swap(arr, high, m);
  47. if(arr[m] > arr[low])
  48. swap(arr, m, low);
  49. pivotKey = arr[low];//此时枢轴值选择为左中右三个数中位数值
  50. while(low < high) {
  51. //可以不移动枢轴值 最后赋值皆可
  52. while(low < high && arr[high] >= pivotKey)
  53. high--;
  54. arr[low] = arr[high]; //改为直接赋值
  55. while(low < high && arr[low] <= pivotKey)
  56. low++;
  57. arr[high] = arr[low];
  58. }
  59. arr[low] = pivotKey;
  60. return low;
  61. }
  62. public static void swap(int[] arr , int i, int j) {
  63. //交换数组两元素
  64. int temp = arr[i];
  65. arr[i] = arr[j];
  66. arr[j] = temp;
  67. }
  68. public static void main(String[] args) {
  69. int[] arrTest = {50,10,90,30,70,40,80,60,20};
  70. System.out.println("before: " + Arrays.toString(arrTest));
  71. quickSort(arrTest);
  72. System.out.println("after: " + Arrays.toString(arrTest));
  73. }
  74. }

快排和归并的示意图:


 

再加一个啊哈磊的图

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/462127
推荐阅读
相关标签
  

闽ICP备14008679号