image.png

image.png

稳定算法很重要,稳定算法比较次数少。

插入排序:

类比就是打扑克,
假设有个这样的问题:打扑克。分成两部分:一部分是你手里的牌(已经排好序),一部分是要拿的牌(无序)。把一个无序的数列一个个插入到有序数列中。一个有序的数组,我们往里面添加一个新的数据后,如何继续保持数据有序呢?我们只要遍历数组,找到数据应该插入的位置将其插入即可。画图演示:以上这种往一个有序的集合里面插入元素,插入后序列仍然有序这就是插入排序算法思路。理解起来不难吧。那么插入排序具体是怎么实现呢?具体步骤如下:1.将数组分成已排序段和未排序段。初始化时已排序端只有一个元素2.到未排序段取元素插入到已排序段,并保证插入后仍然有序3.重复执行上述操作,直到未排序段元素全部加完。有几种数据结构,用什么数据结构来实现。数组,链表,2个数组。

image.png

代码实现:

  1. int n = arr.length;
  2. for(int i = 1;i<n;i++){//未排序数组
  3. int j = i-1;//排序数组的末尾
  4. int data = arr[i];
  5. for(;j>=0;j--){
  6. if(arr[j]>data){
  7. //数组向后移动
  8. arr[j+1] = arr[j];
  9. continue;
  10. }
  11. //找到比插入数据小的位置,跳出循环
  12. break;
  13. }
  14. arr[j+1]=data;//给新的数组位置赋值
  15. }

希尔排序

来看一个具体的过程:
按照一个增量分段:add=n/2 n=10 =>5,2,1
7 8 9 0 4 3 1 2 5 10我们取的这个增量分别就是5 2 1
7 8 9 0 4 3 1 2 5 10:分出来的数组元素都是一样的
完成一次排序:3 1 2 0 4 7 8 9 5

3 2 4 8 5:取增量为2的分为一组了
最后一次我们就取增量为1的分组:就是一个完整的序列。

image.png

希尔排序是插入排序的增强版本,设置步长就是为了使break执行的更多。

  1. int n = arr.length;
  2. for (int add = n / 2; add >= 1; add /= 2) {
  3. for (int i = add; i < n; i += add) {//未排序数组
  4. int j = i - add;//排序数组的末尾
  5. int data = arr[i];
  6. for (; j >= 0; j -= add) {
  7. if (arr[j] > data) {
  8. //数组向后移动
  9. arr[j + add] = arr[j];
  10. continue;
  11. }
  12. break;
  13. }
  14. arr[j + add] = data;//给新的数组位置赋值
  15. }
  16. }

归并排序

image.png
分析时间复杂度:nlogn

  1. public static void megerSort(int[] arr, int left, int right) {
  2. if (left < right) {
  3. int mid = (left + right) / 2;
  4. //左边开始递
  5. megerSort(arr, left, mid);
  6. //右边开始递
  7. megerSort(arr, mid + 1, right);
  8. //开始合并数组
  9. mergeArrarys(arr, left, mid, right);
  10. }
  11. }
  12. //合并数组
  13. private static void mergeArrarys(int[] arr, int left, int mid, int right) {
  14. //创新新的数组
  15. int[] tmp = new int[arr.length];
  16. int point1 = left;//左边数组的第一个
  17. int point2 = mid + 1;//右边数组的第一个
  18. int loc = left;//新的数组的开始位置
  19. while (point1 <= mid && point2 <= right) {
  20. if (arr[point1] < arr[point2]) {
  21. //左边小的话,进入临时数组中
  22. tmp[loc] = arr[point1];
  23. point1++;
  24. loc++;
  25. } else {
  26. tmp[loc] = arr[point2];
  27. point2++;
  28. loc++;
  29. }
  30. }
  31. //
  32. //左边的数组可能没有完,继续添加在临时数组中
  33. while (point1 <= mid) {
  34. tmp[loc++] = arr[point1++];
  35. }
  36. //右边的数组可能没有完,继续添加在临时数组中
  37. while (point2 <= right) {
  38. tmp[loc++] = arr[point2++];
  39. }
  40. //复制临时数组到原数组
  41. for (int i = left; i <= right; i++) {
  42. arr[i] = tmp[i];
  43. }
  44. }

选择排序

快速排序

image.png
image.png

image.png

image.png

  1. package com.sort;
  2. /**
  3. * @author yangkang
  4. * @version 1.0
  5. * @description: 插入排序
  6. * @date 2022/3/12 23:39
  7. */
  8. public class InsertSort {
  9. public static void main(String[] args) {
  10. int[] arr = {9, 13, 11, 10, 12, 5, 6};
  11. //9,13
  12. //9,13,13,10,12,5,6
  13. //9,11,13,10,12,5,6
  14. insertSort2(arr);
  15. // insertSort(arr);
  16. for (int i : arr) {
  17. System.out.println(i);
  18. }
  19. }
  20. private static void insertSort2(int[] arr) {
  21. int n = arr.length;
  22. for(int i = 1;i<n;i++){
  23. int data = arr[i];
  24. int j = i-1;
  25. for(;j>=0;j--){
  26. if(arr[j]>data){
  27. arr[j+1] = arr[j];
  28. continue;
  29. }
  30. break;
  31. }
  32. arr[j+1] = data;
  33. }
  34. }
  35. private static void insertSort(int[] arr) {
  36. int n = arr.length;
  37. //9, 13, 11, 10, 12, 5, 6
  38. for(int i = 1;i<n;i++){//为排序的数组开始,从下标1开始
  39. int data = arr[i];
  40. int j =i-1;//排序的末尾
  41. for(;j>=0;j--){
  42. if(arr[j]>data){
  43. arr[j+1] = arr[j];//数组往后面移动
  44. continue;
  45. }
  46. break;//找到了比他小的值
  47. }
  48. arr[j+1] = data;
  49. }
  50. }
  51. }