• 八种基础排序算法


    排序算法

    • 排序算法的介绍:
      • 排序也称排序算法(sort Alogrithm),排序时将以组数据,依指定顺序进行排序的过程。
      • 排序的分类:
        • 内部排序:
          • 指将需要处理的所有数据加载到内部存储器中进行排序。
        • 外部排序:
          • 数据量过大,无法加载到内存中,需要借助外部存储进行排序。
        • 常见的排序算法分类:
          • 在这里插入图片描述

          • 排序算法的复杂度和稳定性:

            • 在这里插入图片描述

    冒泡排序

    • 基本介绍:

      • 冒泡排序(Bubble Sorting) 的基本思想:

        • 通过对待排序序列从前向后(从下标较小的元素开始),依次比较相邻元素的值,若发现逆序则交换,使较大相邻的元素从前向后移动,就像水下的气泡一样逐渐升起来。

        • 因排序的过程中,各元素不断接近自己的位置,**如果下 一趟比较下来没有进行交换,就说明序列有序,因此要在排序过程中设置一个标志的flag判断元素是否进行过交换。从而减少不比较的比较

        • 冒泡图解:

            1. 将列表[1,3,5,4,2]进行排序,把元素想象成一个小球。如下图所示:

              img

              第一次循环进行交换最大值5浮到顶部。接下来进行第二次循环: 5在第一次已经冒出来,第二次循环不需要进行交换比较

              img

              第三次循环[4,5]已经冒出来,第三次循环不需要进行交换比较

              img

              第四次循环:到第4次循环结束之后,全部元素交换完成,得到一个有序的列表。

              img

          • 来源:图解冒泡来自

          • 时间复杂度: O ( n 2 ) O(n^2) O(n2)

          • 代码实现:

            • public class BubbleSort {
                  public static void main(String[] args) {
                      int[] a = {5, 4, 3, 2, 1};
                      for (int i = 0; i < 5 - 1; ++ i) {
                          boolean flag = true;
                          for (int j = 0; j < 5 - i - 1; ++ j) {
                              if (a[j] > a[j + 1]) {
                                  int temp = a[j];
                                  a[j] = a[j + 1];
                                  a[j + 1] = temp;
                                  flag = false;
                              }
                          }
                          for (int j = 0; j < 5; ++ j) {
                              System.out.print(a[j] + " ");
                          }
                          System.out.println();
                          if (flag) break;
                      }
                  }
              }
              
              
          • 冒泡排序小结:

              1. 一共进行数组大小 - 1次 的循环
              2. 每一趟排序的次数在逐渐减少。
              3. 如果我们发现在某一趟排序中,没有发生依次交换,可以提前结束冒泡排序。这就是一个优化,flag 变量做这一步。

    选择排序

    • 基本思想:

      • 选择排序(select sorting)也是一种简单的排序方法。它的 基本思想 是:第一次从arr[0] ~ arr[n-1]中选这最小的值,与arr[0]交换,第二次从arr[1]arr[n-1]中选择最小的值,与arr[1]交换,第i次从arr[i-1]arr[n-1]中选取最小值,与arr[i-1]交换。。。。. 第n-1次 从arr[n-2]~arr[n-1]选最小的值,与arr[n-2]交换,总共通过 n - 1次,的到一个安排序序码从小到大大排序的有序序列。
    • 图解:

      • 在这里插入图片描述
    • 代码思路:

        1. 选择排序一共数组大小 -1 轮排序。
        2. 每 1 轮排序,又是一个循环,循环规则如下
            1. 先假定当前这个数是最小的。
            2. 然后和后面的每个数进行比较,如果发现有比当前数更小的数,就重新确定最小的数,并的到下标。
            3. 当遍历到数组最后时,本轮得到本轮最小的数的下标。
            4. 交换(看代码)
    • 时间复杂度: O ( n 2 ) O(n^2) O(n2)

    • 代码实现:

      • public class SelectSort {
            public static void main(String[] args) {
                int[] arr = {8, 3, 2, 1, 7, 4, 6, 5};
                for (int i = 0; i < 8; ++ i) {
                    int idx = i;
                    for (int j = i; j < 8; ++ j) {
                        if (arr[idx] > arr[j]) {
                            idx = j;
                        }
                    }
                    int temp = arr[idx];
                    arr[idx] = arr[i];
                    arr[i] = temp;
                    for (int j = 0; j < 8; ++ j) {
                        System.out.print(arr[j] + " ");
                    }
                    System.out.println();
                }
            }
        }
        
        

    插入排序

    • 插入排序介绍:

      • 插入式排序属于内部排序法,对于欲排序的元素以插入的方式找到该元素的适当位置,以达到排序的目的。
    • 插入排序的思想:

      • 把n个待排序的元素看成为,一个有序和一个无序表,开始时有序表中只包含一个元素,无序表中包含了n-1个元素, 排序过程中每次从无序表中取出第一个元素,把它的排序码一次与有序表元素的排序码进行比较,将它插入到有序表中的适当位子,使之称为新的有序表。
      • 就像一手扑克牌整理成有序的。
    • 图解:

      • 在这里插入图片描述
    • 代码实现:

      • public class InsertSort {
            public static void main(String[] args) {
                int[] arr = {17, 3, 25, 14, 20, 9};
                for (int i = 1; i < arr.length; ++ i) {
                    int insertValue = arr[i];
                    int insertIndex = i - 1;//表示有序表的最后这个元素的下标
                    //还没找到位置
                    while (insertIndex >= 0 && insertValue < arr[insertIndex]) {
                        arr[insertIndex + 1] = arr[insertIndex];
                        insertIndex -= 1;
                    }
                    //退出while循环 说明插入的位置被找到;额
                    arr[insertIndex + 1] = insertValue;
                    for (int j = 0; j <= i; ++ j) {
                        System.out.print(arr[j] + " ");
                    }
                    System.out.println();
                }
        
            }
        }
        
        
      • 运行效果图:

        • 在这里插入图片描述

    希尔排序

    是将简单的插入排序进行优化。

    • 希尔排序的介绍:

      • 希尔排序是希尔(Donald Shell)于1959年提出的一种排序算法。希尔排序也是一种插入排序,它是简单排序经过改良后的一个 更高效的版本,也被称为缩小增量排序。
    • 希尔排序的算法思想:

      • 希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量的减少,每组包含的关键词越来越多,当增量减到 1 时,整个文件恰好被分成一组,使算法停止。
    • 图解希尔排序:

      • 原始数组 以下数据元素颜色相同为一组

        • 在这里插入图片描述
      • 初始增量 g a p = l e n g t h / 2 = 5 gap=length/2=5 gap=length/2=5 ,意味着真个数组被分为 5 5 5 组, [ 8 , 3 ] [ 9 , 5 ] [ 1 , 4 ] [ 7 , 6 ] [ 2 , 0 ] [8,3][9,5][1,4][7,6][2,0] [8,3][9,5][1,4][7,6][2,0]

        • 在这里插入图片描述

        • 此状态到下一个状态的代码:

          • for (int i = 5; i < arr.length; ++ i) {
                      for (int j = i - 5; j >= 0; j -= 5) {
                          //如果当前元素大于加上步长的元素,说明交换
                          if (arr[j] > arr[j + 5]) {
                              int temp = arr[j];
                              arr[j] = arr[j + 5];
                              arr[j + 5] = temp;
                          }
                      }
                  }
                  System.out.println("希尔排序第一轮"+Arrays.toString(arr));
            
      • 对这五组分别进行直接 插入排序, 结果如下,可以看到,像3, 5,6这些小的元素都被掉到了最前面了,然后缩小增量 g a p = 5 / 2 = 2 gap=5/2=2 gap=5/2=2,数组被分为 2 组 [ 3 , 1 , 0 , 9 , 7 ] [ 5 , 6 , 8 , 4 , 2 ] [3,1,0,9,7][5,6,8,4,2] [3,1,0,9,7][5,6,8,4,2]

        • 在这里插入图片描述

        • 此状态到下一个状态的代码:

          • for (int i = 2; i < arr.length; ++ i) {
                for (int j = i - 2; j >= 0; j -= 2) {
                    //如果当前元素大于加上步长的元素,说明交换
                    if (arr[j] > arr[j + 2]) {
                        int temp = arr[j];
                        arr[j] = arr[j + 2];
                        arr[j + 2] = temp;
                    }
                }
            }
            System.out.println("希尔排序第二轮"+Arrays.toString(arr));
            
      • 对以上 2 组再分别进行直接插入排序,结果如下,可以看到,此时整个数组的有序程度更异步接近啦。再缩小增量 g a p = 2 / 2 = 1 gap=2/2=1 gap=2/2=1,此时,整个数组为 1 组 [ 0 , 2 , 1 , 4 , 3 , 5 , 7 , 6 , 9 , 8 ] [0,2,1,4,3,5,7,6,9,8] [0,2,1,4,3,5,7,6,9,8]

        • 在这里插入图片描述

        • 此状态到有序的代码:

          • for (int i = 1; i < arr.length; ++ i) {
                for (int j = i - 1; j >= 0; j -= 1) {
                    //如果当前元素大于加上步长的元素,说明交换
                    if (arr[j] > arr[j + 1]) {
                        int temp = arr[j];
                        arr[j] = arr[j + 1];
                        arr[j + 1] = temp;
                    }
                }
            }
            System.out.println("希尔排序第三轮"+Arrays.toString(arr));
            
      • 经过上面的”宏观调控“,整个数组的无序化程度成果喜人。此时,仅仅需要对以上数列简单微调,无需大量移动即可完成整个数组的排序。

    • 时间复杂度: O ( n k ) O(n^k) O(nk) 1.3 <= k <= 2.

    • 将上面的逐步分析使用循环处理:

      • import java.util.Arrays;
        
        public class ShellSort {
            public static void main(String[] args) {
                int[] arr = {8, 9, 1, 7, 2, 3, 5, 4, 6, 0};
                shellSort(arr);
            }
            //使用希尔排序的方式来编写希尔排序
            public static void shellSort(int arr[]) {
        
                for (int gap = arr.length / 2; gap > 0; gap /= 2) {
                    for (int i = gap; i < arr.length; ++ i) {
                        for (int j = i - gap; j >= 0; j -= gap) {
                            if (arr[j] > arr[j + gap]) {
                                int temp = arr[j];
                                arr[j] = arr[j + gap];
                                arr[j + gap] = temp;
                            }
                        }
                    }
                    System.out.println(Arrays.toString(arr));
                }
            }
        }
        
        

    快速排序

    • 快速排序算法介绍:

      • 快速排序(Quicksort)是对冒泡排序的一种改进。

      • 基本思想:

        • 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的左右数据都比另外一部的所有数据都要小,然后再按此方法对着两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
    • 做法:

      • 选择每个子数组中间的一个数作为 基准数,将基准数的右边变成全部大于 基准数的数, 左边全部小于基准数的数。然后再递归处理子数组。
      • 图解此图是以左边的数,以中间的数更好理解:
        • 百度百科
    • 时间复杂度: O ( n l o g 2 n ) O(nlog_2^n) O(nlog2n)

    • 代码实现:

      • import java.util.Arrays;
        
        public class QuickSort {
            public static void main(String[] args) {
                int[] a = {2, 3, 1, 2, 5, 21, 1, 0};
                quickSort(a, 0, a.length - 1);
                System.out.println(Arrays.toString(a));
            }
            public static void quickSort(int a[], int l, int r) {
                if (l >= r) return;
                int i = l - 1;
                int j = r + 1;
                int x = a[(l + r) >> 1];
                while (i < j) {
                    do i ++; while (a[i] < x);
                    do j --; while (a[j] > x);
                    if (i < j) {
                        int temp = a[i];
                        a[i] = a[j];
                        a[j] = temp;
                    }
                }
                quickSort(a, l, j);
                quickSort(a, j + 1, r);
            }
        }
        
      • 输出结果

        • 在这里插入图片描述

    归并排序

    • 归并排序介绍:

      • 归并排序(MERGE-SORT)是利用 归并 的思想实现的排序方法,该算法采用经典的 分治 (divide-and-conquer)策略(分治法将问题 成一些小问题然后递归求解,而 的阶段则是将各分段得到的各答案”修补“在一起,即 分而治之)。

      • 图解算法思想:

        • 说明:
          • 可以看到这种结构很像一颗完全二叉树,本文的归并排序我们采用递归去实现(也可以采用迭代的方法实现)。
          • 阶段可以理解为就是递归拆分子序列的过程。
          • 阶段把原本有序的两个序列 合并成一个有序序列。
    • 归并排序代码实现:

      • import java.util.Arrays;
        
        public class MergeSort {
            public static void main(String[] args) {
                int[] a = {8, 4, 5, 7, 1, 3, 6, 2};
                int[] c = new int[8];
                mergeSort(a, 0, a.length - 1, c);
                System.out.println(Arrays.toString(a));
            }
            public static void mergeSort(int[] a, int l, int r, int[] c) {
                if (l >= r) return;
                int mid = (l + r) >> 1;
                mergeSort(a, l, mid, c);
                mergeSort(a, mid + 1, r, c);
                int i = l;
                int j = mid + 1;
                for (int k = l; k <= r; ++ k) {
                    if (j > r || i <= mid && a[i] <= a[j]) c[k] = a[i ++];
                    else c[k] = a[j ++];
                }
                for (int k = l; k <= r; ++ k) a[k] = c[k];
            }
        }
        
        
      • 运行结果:

        • 在这里插入图片描述

    基数排序

    • 基数排序(桶排序)介绍:

        1. 基数排序(radix sort)属于"分配式排序",又称 “桶子法” (bucket sort)或者bin sort,,顾名思义,它是通过键值的各个位的值,将要排序的元素分配到某些 中,达到排序的效果。
        2. 基数排序法是属于稳定的排序,基数排序法的效率高的稳定性排序算法。
        3. 基数排序是(Radix Sort)是桶排序的扩展。
        4. 基数排序是1887年 赫尔曼·何乐礼 发明的。它的实现:将整数按位数切割成不同的数字,然后按每个数字分别进行比较。
    • 基数排序的基本思想:

        1. 将所有待比较的数值统一为一样长度的数,位数较短的数前面补零。然后,从低位开始,依次进行依次排序。这样从低位排序一直到高位排序完成以后,数列就变成了一个有序序列。

        2. 这样说明,比较难理解,下面图文理解。

          • 数组的初始状态:{53, 3, 542,748,14,214}使用基数排序,进行升序排序

          • 下面是10个桶(表示 0~9 ):

            • 在这里插入图片描述

              ​ 0 1 2 3 4 5 6 7 8 9

            1. 将每个元素的个位取出来,然后看看这个数应该放在那个对应的桶里(以最取出来的数选桶)。

              *在这里插入图片描述

              ​ 0 1 2 3 4 5 6 7 8 9

            2. 按照这个桶的顺序依次,取出数据放回到原来的数组中。

              • {542,53,3,14,214,748}
              • 此时的桶 中的元素还在。
            3. 将每个元素的十位取出来,然后看看这个数应该放在那个对应的桶里(以最取出来的数选桶)。

              • 为了方便先把之气的元素隐藏,但是之前放的元素还再桶里。

              • 在这里插入图片描述

                ​ 0 1 2 3 4 5 6 7 8 9

            4. 按照桶的顺序取出数据放回原来的数组中

              • {3,14,214,542,748,53}
            5. 将每个元素的百位取出来,然后看看这个数应该放在那个对应的桶里(以最取出来的数选桶)。

              • 最后 同理取出来得到数组 {3,14,214,542,748,53}
          • package com.atguigu.sort;
            
            import java.text.SimpleDateFormat;
            import java.util.Arrays;
            import java.util.Date;
            
            public class RadixSort {
            
            	public static void main(String[] args) {
            		int arr[] = { 53, 3, 542, 748, 14, 214};
            		
            		// 80000000 * 11 * 4 / 1024 / 1024 / 1024 =3.3G 
            //		int[] arr = new int[8000000];
            //		for (int i = 0; i < 8000000; i++) {
            //			arr[i] = (int) (Math.random() * 8000000); // 生成一个[0, 8000000) 数
            //		}
            		System.out.println("排序前");
            		Date data1 = new Date();
            		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            		String date1Str = simpleDateFormat.format(data1);
            		System.out.println("排序前的时间是=" + date1Str);
            		
            		radixSort(arr);
            		
            		Date data2 = new Date();
            		String date2Str = simpleDateFormat.format(data2);
            		System.out.println("排序前的时间是=" + date2Str);
            		
            		System.out.println("基数排序后 " + Arrays.toString(arr));
            		
            	}
            
            	//基数排序方法
            	public static void radixSort(int[] arr) {
            		
            		//根据前面的推导过程,我们可以得到最终的基数排序代码
            		
            		//1. 得到数组中最大的数的位数
            		int max = arr[0]; //假设第一数就是最大数
            		for(int i = 1; i < arr.length; i++) {
            			if (arr[i] > max) {
            				max = arr[i];
            			}
            		}
            		//得到最大数是几位数
            		int maxLength = (max + "").length();
            		
            		
            		//定义一个二维数组,表示10个桶, 每个桶就是一个一维数组
            		//说明
            		//1. 二维数组包含10个一维数组
            		//2. 为了防止在放入数的时候,数据溢出,则每个一维数组(桶),大小定为arr.length
            		//3. 名明确,基数排序是使用空间换时间的经典算法
            		int[][] bucket = new int[10][arr.length];
            		
            		//为了记录每个桶中,实际存放了多少个数据,我们定义一个一维数组来记录各个桶的每次放入的数据个数
            		//可以这里理解
            		//比如:bucketElementCounts[0] , 记录的就是  bucket[0] 桶的放入数据个数
            		int[] bucketElementCounts = new int[10];
            		
            		
            		//这里我们使用循环将代码处理
            		
            		for(int i = 0 , n = 1; i < maxLength; i++, n *= 10) {
            			//(针对每个元素的对应位进行排序处理), 第一次是个位,第二次是十位,第三次是百位..
            			for(int j = 0; j < arr.length; j++) {
            				//取出每个元素的对应位的值
            				int digitOfElement = arr[j] / n % 10;
            				//放入到对应的桶中
            				bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
            				bucketElementCounts[digitOfElement]++;
            			}
            			//按照这个桶的顺序(一维数组的下标依次取出数据,放入原来数组)
            			int index = 0;
            			//遍历每一桶,并将桶中是数据,放入到原数组
            			for(int k = 0; k < bucketElementCounts.length; k++) {
            				//如果桶中,有数据,我们才放入到原数组
            				if(bucketElementCounts[k] != 0) {
            					//循环该桶即第k个桶(即第k个一维数组), 放入
            					for(int l = 0; l < bucketElementCounts[k]; l++) {
            						//取出元素放入到arr
            						arr[index++] = bucket[k][l];
            					}
            				}
            				//第i+1轮处理后,需要将每个 bucketElementCounts[k] = 0 !!!!
            				bucketElementCounts[k] = 0;
            				
            			}
            			//System.out.println("第"+(i+1)+"轮,对个位的排序处理 arr =" + Arrays.toString(arr));
            			
            		}
            		
            		/*
            		
            		//第1轮(针对每个元素的个位进行排序处理)
            		for(int j = 0; j < arr.length; j++) {
            			//取出每个元素的个位的值
            			int digitOfElement = arr[j] / 1 % 10;
            			//放入到对应的桶中
            			bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
            			bucketElementCounts[digitOfElement]++;
            		}
            		//按照这个桶的顺序(一维数组的下标依次取出数据,放入原来数组)
            		int index = 0;
            		//遍历每一桶,并将桶中是数据,放入到原数组
            		for(int k = 0; k < bucketElementCounts.length; k++) {
            			//如果桶中,有数据,我们才放入到原数组
            			if(bucketElementCounts[k] != 0) {
            				//循环该桶即第k个桶(即第k个一维数组), 放入
            				for(int l = 0; l < bucketElementCounts[k]; l++) {
            					//取出元素放入到arr
            					arr[index++] = bucket[k][l];
            				}
            			}
            			//第l轮处理后,需要将每个 bucketElementCounts[k] = 0 !!!!
            			bucketElementCounts[k] = 0;
            			
            		}
            		System.out.println("第1轮,对个位的排序处理 arr =" + Arrays.toString(arr));
            		
            		
            		//==========================================
            		
            		//第2轮(针对每个元素的十位进行排序处理)
            		for (int j = 0; j < arr.length; j++) {
            			// 取出每个元素的十位的值
            			int digitOfElement = arr[j] / 10  % 10; //748 / 10 => 74 % 10 => 4
            			// 放入到对应的桶中
            			bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
            			bucketElementCounts[digitOfElement]++;
            		}
            		// 按照这个桶的顺序(一维数组的下标依次取出数据,放入原来数组)
            		index = 0;
            		// 遍历每一桶,并将桶中是数据,放入到原数组
            		for (int k = 0; k < bucketElementCounts.length; k++) {
            			// 如果桶中,有数据,我们才放入到原数组
            			if (bucketElementCounts[k] != 0) {
            				// 循环该桶即第k个桶(即第k个一维数组), 放入
            				for (int l = 0; l < bucketElementCounts[k]; l++) {
            					// 取出元素放入到arr
            					arr[index++] = bucket[k][l];
            				}
            			}
            			//第2轮处理后,需要将每个 bucketElementCounts[k] = 0 !!!!
            			bucketElementCounts[k] = 0;
            		}
            		System.out.println("第2轮,对个位的排序处理 arr =" + Arrays.toString(arr));
            		
            		
            		//第3轮(针对每个元素的百位进行排序处理)
            		for (int j = 0; j < arr.length; j++) {
            			// 取出每个元素的百位的值
            			int digitOfElement = arr[j] / 100 % 10; // 748 / 100 => 7 % 10 = 7
            			// 放入到对应的桶中
            			bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
            			bucketElementCounts[digitOfElement]++;
            		}
            		// 按照这个桶的顺序(一维数组的下标依次取出数据,放入原来数组)
            		index = 0;
            		// 遍历每一桶,并将桶中是数据,放入到原数组
            		for (int k = 0; k < bucketElementCounts.length; k++) {
            			// 如果桶中,有数据,我们才放入到原数组
            			if (bucketElementCounts[k] != 0) {
            				// 循环该桶即第k个桶(即第k个一维数组), 放入
            				for (int l = 0; l < bucketElementCounts[k]; l++) {
            					// 取出元素放入到arr
            					arr[index++] = bucket[k][l];
            				}
            			}
            			//第3轮处理后,需要将每个 bucketElementCounts[k] = 0 !!!!
            			bucketElementCounts[k] = 0;
            		}
            		System.out.println("第3轮,对个位的排序处理 arr =" + Arrays.toString(arr)); */
            		
            	}
            }
            
            

    堆排序

      1. 堆排序是利用 这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏、最好,平均时间复杂度均为 O ( l o n g n ) O(long^n) O(longn),它也是不稳定排序

      2. 堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆,**注意:**没有要求结点的左孩子和右孩子的值的关系大小。

      3. 每个结点的值都小于或者等于其左右孩子结点的值,称为小顶堆。

      4. 大顶堆举例说明在这里插入图片描述

      5. 小顶堆:

        • arr[i] <= arr[2 * i + 1] && arr[i] <= arr[2 * i + 2] //i对应的第几个结点,i从0开始编号
          
      6. 一般 升序采用大顶堆降序采用小顶堆

    堆排序思想:

    1. 将待排序序列构造成一个大顶堆。
    2. 此时整个序列的最大值就是堆顶的根结点.
    3. 将其与末尾元素进行交换,此时末尾就成为最大值。
    4. 将剩余 n - 1 个元素重新构一个堆,这样就会得到 n 个元素的次小值。如此反复执行,便能得到一个有序序列了···
    package com.yanxun.Tree;
    
    import java.lang.reflect.Array;
    import java.util.Arrays;
    
    public class HeapSort {
        public static void main(String[] args) {
            int[] a = {4, 6, 8, 5, 9};
            heapSort(a);
            System.out.println(Arrays.toString(a));
        }
    
        public static void heapSort(int[] arr) {
            System.out.println("堆排序");
            for (int i = arr.length/2 - 1; i >= 0; i --) {
                adjustHeap(arr, i, arr.length);
            }
    
            for (int j = arr.length - 1; j > 0; -- j) {
                int temp = arr[j];
                arr[j] = arr[0];
                arr[0] = temp;
                adjustHeap(arr, 0, j);
            }
        }
    
        public static void adjustHeap(int[] arr, int i, int length) {
            int temp = arr[i];//取出当前元素的值
            //调整
            for (int k = i * 2 + 1; k < length; k = k * 2 + 1) {
                if (k + 1 < length && arr[k] < arr[k + 1]) {//比较i的左右结点大小
                    k ++;
                }
                if (arr[k] > temp) {
                    arr[i] = arr[k];//把较大的值向上调整
                    i = k;
                } else {
                    break;
                }
    
            }
    
            arr[i] = temp;
        }
    }
    
    
    
    
    追求吾之所爱
  • 相关阅读:
    任意指定一个key获取该key所处在哪个node节点
    记一次mysql的问题处理@20181225
    Vue 自定义校验规则
    Vue 渲染状态标签
    Vue Token拦截跳转
    vue 组件路由问题
    vue npm运行报错
    Vue复习(一)
    从客户端中检测到有潜在危险的 Request.Form
    EF Core for MySql踩坑(二)
  • 原文地址:https://www.cnblogs.com/rstz/p/14390981.html
Copyright © 2020-2023  润新知