堆排序可以说是一种利用堆的概念来排序的选择排序。分为两种方法:
- 大顶堆:每个节点的值都大于或等于其子节点的值,在堆排序算法中用于升序排列;
- 小顶堆:每个节点的值都小于或等于其子节点的值,在堆排序算法中用于降序排列;
算法步骤
-
创建一个堆 H[0……n-1];
-
把堆首(最大值)和堆尾互换;
-
把堆的尺寸缩小 1,并调用 shift_down(0),目的是把新的数组顶端数据调整到相应位置;
-
重复步骤 2,直到堆的尺寸为 1。
JavaScript
1 var len; // 因为声明的多个函数都需要数据长度,所以把len设置成为全局变量 2 3 function buildMaxHeap(arr) { // 建立大顶堆 4 len = arr.length; 5 for (var i = Math.floor(len/2); i >= 0; i--) { 6 heapify(arr, i); 7 } 8 } 9 10 function heapify(arr, i) { // 堆调整 11 var left = 2 * i + 1, 12 right = 2 * i + 2, 13 largest = i; 14 15 if (left < len && arr[left] > arr[largest]) { 16 largest = left; 17 } 18 19 if (right < len && arr[right] > arr[largest]) { 20 largest = right; 21 } 22 23 if (largest != i) { 24 swap(arr, i, largest); 25 heapify(arr, largest); 26 } 27 } 28 29 function swap(arr, i, j) { 30 var temp = arr[i]; 31 arr[i] = arr[j]; 32 arr[j] = temp; 33 } 34 35 function heapSort(arr) { 36 buildMaxHeap(arr); 37 38 for (var i = arr.length-1; i > 0; i--) { 39 swap(arr, 0, i); 40 len--; 41 heapify(arr, 0); 42 } 43 return arr; 44 }
Python
1 def buildMaxHeap(arr): 2 import math 3 for i in range(math.floor(len(arr)/2),-1,-1): 4 heapify(arr,i) 5 6 def heapify(arr, i): 7 left = 2*i+1 8 right = 2*i+2 9 largest = i 10 if left < arrLen and arr[left] > arr[largest]: 11 largest = left 12 if right < arrLen and arr[right] > arr[largest]: 13 largest = right 14 15 if largest != i: 16 swap(arr, i, largest) 17 heapify(arr, largest) 18 19 def swap(arr, i, j): 20 arr[i], arr[j] = arr[j], arr[i] 21 22 def heapSort(arr): 23 global arrLen 24 arrLen = len(arr) 25 buildMaxHeap(arr) 26 for i in range(len(arr)-1,0,-1): 27 swap(arr,0,i) 28 arrLen -=1 29 heapify(arr, 0) 30 return arr
C语言
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 void swap(int *a, int *b) { 5 int temp = *b; 6 *b = *a; 7 *a = temp; 8 } 9 10 void max_heapify(int arr[], int start, int end) { 11 // 建立父節點指標和子節點指標 12 int dad = start; 13 int son = dad * 2 + 1; 14 while (son <= end) { // 若子節點指標在範圍內才做比較 15 if (son + 1 <= end && arr[son] < arr[son + 1]) // 先比較兩個子節點大小,選擇最大的 16 son++; 17 if (arr[dad] > arr[son]) //如果父節點大於子節點代表調整完畢,直接跳出函數 18 return; 19 else { // 否則交換父子內容再繼續子節點和孫節點比較 20 swap(&arr[dad], &arr[son]); 21 dad = son; 22 son = dad * 2 + 1; 23 } 24 } 25 } 26 27 void heap_sort(int arr[], int len) { 28 int i; 29 // 初始化,i從最後一個父節點開始調整 30 for (i = len / 2 - 1; i >= 0; i--) 31 max_heapify(arr, i, len - 1); 32 // 先將第一個元素和已排好元素前一位做交換,再重新調整,直到排序完畢 33 for (i = len - 1; i > 0; i--) { 34 swap(&arr[0], &arr[i]); 35 max_heapify(arr, 0, i - 1); 36 } 37 } 38 39 int main() { 40 int arr[] = { 3, 5, 3, 0, 8, 6, 1, 5, 8, 6, 2, 4, 9, 4, 7, 0, 1, 8, 9, 7, 3, 1, 2, 5, 9, 7, 4, 0, 2, 6 }; 41 int len = (int) sizeof(arr) / sizeof(*arr); 42 heap_sort(arr, len); 43 int i; 44 for (i = 0; i < len; i++) 45 printf("%d ", arr[i]); 46 printf(" "); 47 return 0;
C++
1 #include <iostream> 2 #include <algorithm> 3 using namespace std; 4 5 void max_heapify(int arr[], int start, int end) { 6 // 建立父節點指標和子節點指標 7 int dad = start; 8 int son = dad * 2 + 1; 9 while (son <= end) { // 若子節點指標在範圍內才做比較 10 if (son + 1 <= end && arr[son] < arr[son + 1]) // 先比較兩個子節點大小,選擇最大的 11 son++; 12 if (arr[dad] > arr[son]) // 如果父節點大於子節點代表調整完畢,直接跳出函數 13 return; 14 else { // 否則交換父子內容再繼續子節點和孫節點比較 15 swap(arr[dad], arr[son]); 16 dad = son; 17 son = dad * 2 + 1; 18 } 19 } 20 } 21 22 void heap_sort(int arr[], int len) { 23 // 初始化,i從最後一個父節點開始調整 24 for (int i = len / 2 - 1; i >= 0; i--) 25 max_heapify(arr, i, len - 1); 26 // 先將第一個元素和已经排好的元素前一位做交換,再從新調整(刚调整的元素之前的元素),直到排序完畢 27 for (int i = len - 1; i > 0; i--) { 28 swap(arr[0], arr[i]); 29 max_heapify(arr, 0, i - 1); 30 } 31 } 32 33 int main() { 34 int arr[] = { 3, 5, 3, 0, 8, 6, 1, 5, 8, 6, 2, 4, 9, 4, 7, 0, 1, 8, 9, 7, 3, 1, 2, 5, 9, 7, 4, 0, 2, 6 }; 35 int len = (int) sizeof(arr) / sizeof(*arr); 36 heap_sort(arr, len); 37 for (int i = 0; i < len; i++) 38 cout << arr[i] << ' '; 39 cout << endl; 40 return 0; 41 }