Java/C++中的HeapSort实现
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