八种基础排序算法

排序算法

  • 排序算法的介绍:
    • 排序也称排序算法(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;
    }
}



追求吾之所爱
原文地址:https://www.cnblogs.com/rstz/p/14390981.html