Java/C++中的HeapSort实现

时间:2020-02-23 14:34:49  来源:igfitidea点击:

Heapsort是一种使用二进制堆进行排序的排序算法。
堆可以有两种类型,最小堆和最大堆。

Heapsort是选择排序的改进版本。

在本教程中,我们将使用最大堆来实现Heapsort。

最大堆遵循父元素始终大于其子元素的属性。
这意味着在最大堆中,根始终是所有元素的最大值。
Heapsort使用此属性以排序的方式排列元素。

算法

Heapsort的算法如下:

  • 从输入数组构建最大堆。

  • 将root(最大值)替换为堆的最后一项。

  • 将堆大小减小1。

  • 通过调用DownHeapify来堆满树的根

  • 当堆的大小大于1时,请重复步骤2至4。

在每次迭代中,我们采用最大元素并将其放在堆的末尾。
然后我们减小堆的大小。
在进行此过程时,我们将从最后开始对数组进行排序。

我们将调用函数downheapify()来确保在减小大小后满足了heap属性。

堆排序实现

为了堆积数组,我们使用了一个从根到叶节点的递归函数。
每个节点上的此功能都会将父级与其子级进行比较。
如果父节点的值小于其子节点的值,它将交换值。
此交换可确保满足最大堆属性。

执行交换后,如果进一步调用子代上的downheapify函数。

每次在堆中添加或者删除元素时都需要调用此函数。

在堆中,孩子的位置由下式给出:

Left child : (2*i) + 1
Right child : (2*i) + 2 

downheapify的代码如下:

static void downheapify(int arr[], int n, int i)
  {
      int largest = i;
      int l = 2*i + 1;
      int r = 2*i + 2;

      //finding the maximum of left and right
      if (l < n && arr[l] > arr[largest])
          largest = l;

      if (r < n && arr[r] > arr[largest])
          largest = r;

      //swapping if child >parent
      if (largest != i)
      {
          int swap = arr[i];
          arr[i] = arr[largest];
          arr[largest] = swap;

          downheapify(arr, n, largest);
      }
  }

要对数组排序,我们首先需要从中创建一个堆。
这是通过以下代码行完成的:

for (int i = n/2 - 1; i >= 0; i--)
          downheapify(arr, n, i);

我们只需要在调用downheapify时考虑非叶子节点,因为叶子节点已经满足了heap属性。

下一步是从根位置提取元素,然后将其与堆的最后位置交换。
完成此操作后,我们将减小堆的大小,然后再次调用downheapify。
执行此操作的代码行是:

for (int i=n-1; i>0; i--)
      {
        //swap the last element with root
          int temp = arr[0];
          arr[0] = arr[i];
          arr[i] = temp;

        //i is the size of the reduced heap
         downheapify(arr, i, 0);
      }

排序功能的完整代码为:

public static void sort(int arr[])
  {
      int n = arr.length;

    //build heap by calling heapify on non leaf elements
      for (int i = n/2 - 1; i >= 0; i--)
          downheapify(arr, n, i);

   //extract elements from the root and call healpify
      for (int i=n-1; i>0; i--)
      {
        //swap the last element with root
          int temp = arr[0];
          arr[0] = arr[i];
          arr[i] = temp;

          //i is the size of the reduced heap
          downheapify(arr, i, 0);
      }
  }

除了这两个函数外,我们还需要一个函数来打印数组。

打印功能如下:

static void printArray(int arr[])
  {
      int n = arr.length;
      for (int i=0; i<n; ++i)
          System.out.print(arr[i]+" ");
      System.out.println();
  }

使用这三个功能,我们可以成功实现Heapsort。

完整的代码

Heapsort的完整代码如下:

1. Java中的堆排序

package com.theitroad;

public class Main {
  static void downheapify(int arr[], int n, int i)
  {
      int largest = i;
      int l = 2*i + 1;
      int r = 2*i + 2;

      //finding the maximum of left and right
      if (l < n && arr[l] > arr[largest])
          largest = l;

      if (r < n && arr[r] > arr[largest])
          largest = r;

      //swapping if child >parent
      if (largest != i)
      {
          int swap = arr[i];
          arr[i] = arr[largest];
          arr[largest] = swap;

          downheapify(arr, n, largest);
      }
  }

  public static void sort(int arr[])
  {
      int n = arr.length;

    //build heap by calling heapify on non leaf elements
      for (int i = n/2 - 1; i >= 0; i--)
          downheapify(arr, n, i);

   //extract elements from the root and call healpify
      for (int i=n-1; i>0; i--)
      {
        //swap the last element with root
          int temp = arr[0];
          arr[0] = arr[i];
          arr[i] = temp;

          //i is the size of the reduced heap
          downheapify(arr, i, 0);
      }
  }
  static void printArray(int arr[])
  {
      int n = arr.length;
      for (int i=0; i<n; ++i)
          System.out.print(arr[i]+" ");
      System.out.println();
  }
  public static void main(String[] arg)
  {
      int arr[] = {1, 10, 2, 3, 4, 1, 2, 100,23, 2};
      int n = arr.length;
      sort(arr);
      System.out.println("Sorted array is");
      printArray(arr);

  }

}

2. C++中的堆排序

#include <iostream> 

using namespace std; 

void downheapify(int arr[], int n, int i) 
{ 
  int largest = i; 
  int l = 2*i + 1; 
  int r = 2*i + 2; 

  if (l < n && arr[l] > arr[largest]) 
      largest = l; 

  if (r < n && arr[r] > arr[largest]) 
      largest = r; 
 
  if (largest != i) 
  { 
       swap(arr[i], arr[largest]);           downheapify(arr, n, largest); 
  } 
} 

void heapSort(int arr[], int n) 
{ 
  
  for (int i = n/2 - 1; i >= 0; i--) 
      heapify(arr, n, i); 

  
  for (int i=n-1; i>0; i--) 
  { 
     
      swap(arr[0], arr[i]); 

      heapify(arr, i, 0); 
  } 
} 
 
void printArray(int arr[], int n) 
{ 
  for (int i=0; i<n; ++i) 
      cout << arr[i] << " "; 
  cout << "\n"; 
} 

int main() 
{ 
 int arr[] = {1, 10, 2, 3, 4, 1, 2, 100,23, 2}; 
  int n = sizeof(arr)/sizeof(arr[0]); 

  heapSort(arr, n); 

  cout << "Sorted array is \n"; 
  printArray(arr, n); 
} 

Output : 

Sorted array is
1 1 2 2 2 3 4 10 23 100