Java 常见例子

堆排序利用堆的特性对数组进行排序。它涉及构建一个用于递增顺序排序的最大堆,其中在根处包含堆的最大元素。对于降序排序,使用最小堆,它在根处包含堆的最小元素。堆排序的升序排序的过程步骤总结如下:

  • 第1步:构建一个最大堆,其中根部包含堆的最大元素
  • 第 2 步: 将堆的最后一个元素与根元素交换,并从堆中删除最后一个元素。对其余元素重复步骤 1。

示例:

要了解堆排序,让我们考虑一个未排序的数组[10, 1, 23, 50, 7, -4] 并讨论按升序对数组进行排序所采取的每个步骤。

下图中显示了输入数组和最大堆的堆结构。堆的根元素的索引号为0。在最大堆中,堆的最大元素始终位于根。

Java 堆排序

构建初始最大堆后,堆的最后一个元素与根元素以及包含数组中最大的数将从堆中删除。之后,对堆中剩余的元素使用heapify函数,使其成为最大堆,元素数量将减少1。这个过程一直持续到堆中的元素数量为1。此时,数组将被排序。

Java 堆排序

上图描述了从堆中消除最大元素以及从堆的剩余元素形成最大堆。该过程的最终结果是一个升序排序的数组。

堆排序的实现

public class MyClass {
  // 调用heapify函数的堆排序函数
  //构建最大堆,然后交换最后一个元素
  // 第一个元素的最大堆
  //从堆中排除最后一个元素并重建堆
  static void heapsort(int Array[]) {
    int n = Array.length;
    int temp;

    for(int i = n/2; i >= 0; i--) {
      heapify(Array, n-1, i);
    }

    for(int i = n - 1; i >= 0; i--) {
      //将最大堆的最后一个元素与第一个元素交换
      temp = Array[i];
      Array[i] = Array[0];
      Array[0] = temp;

      //从堆中排除最后一个元素并重建堆
      heapify(Array, i-1, 0);
    }
  }

  // heapify函数用于构建最大堆
  //最大堆在根处有最大元素,这意味着
  //数组的第一个元素将是最大堆中的最大值
  static void heapify(int Array[], int n, int i) {
    int max = i;
    int left = 2*i + 1;
    int right = 2*i + 2;

    //如果左边元素大于根
    if(left <= n && Array[left] > Array[max]) {
      max = left;
    }

    //如果右侧元素大于根
    if(right <= n && Array[right] > Array[max]) {
      max = right;
    }

    //如果最大值不是i
    if(max != i) {
      int temp = Array[i];
      Array[i] = Array[max];
      Array[max] = temp;
      
      //递归地堆化受影响的子树
      heapify(Array, n, max); 
    }
  }

  //打印数组的函数
  static void PrintArray(int Array[]) { 
    int n = Array.length; 
    for (int i=0; i<n; i++) {  
      System.out.print(Array[i] + " "); 
    }
    System.out.println(); 
  } 

  //测试代码
  public static void main(String[] args) {
    int[] MyArray = {10, 1, 23, 50, 7, -4};
    int n = MyArray.length;
    System.out.println("原始数组");
    PrintArray(MyArray);

    heapsort(MyArray);
    System.out.println("\n排序数组");
    PrintArray(MyArray); 
  }
} 

上面的代码将给出以下输出:

原始数组
10 1 23 50 7 -4 

排序数组
-4 1 7 10 23 50 

时间复杂度:

创建堆的时间复杂度为θ(N),创建最大堆的时间复杂度为θ(logN) em> 堆排序的总体时间复杂度为 θ(NlogN)