之前的博客介紹介紹了數組的兩種排序算法:插入排序和歸並排序(採用遞歸),見鏈接http://blog.csdn.net/u013165521/article/details/46845033。
本篇博客,介紹還有一種排序算法:堆排序。
(內容參照算法導論)
一、堆的概念
所謂堆,它是一個數組,也能夠被看成一個近似的全然二叉樹。樹上每一個結點相應數組的一個元素。二叉堆分為二種:最大堆和最小堆。本文主要介紹最大堆,最小堆類似。最大堆的特點:對於隨意某個結點,該結點的值大於左孩子、右孩子的值,可是左右孩子的值沒有要求。
二、堆排序算法
堆排序算法調用函數Build_max_heap將輸入數組array[1..n]建立成堆。當中n表示數組長度。由於建立堆后,數組的最大元素被存放在根節點A[1],通過將A[1]與數組最后一個元素進行交換。將最大元素后移,實現排序。
可是,交換后新的根節點可能不滿足堆的特點,所以須要調用子函數Max_heapify對剩余的數組元素進行最大堆性質的維護。堆排序算法。通過不斷反復這個過程(n-1)次,實現數組的從小到大排序(由於採用最大堆)。
對於上面提及的兩個子函數進行簡要介紹。
函數Build_max_heap的作用:建堆。
由於子數組A(n/2+1..n)是樹的葉子節點,不須要進行堆的維護。
所以。僅僅須要對A[1..n/2]數組元素進行維護。就可構建堆。
函數Max_heapify的作用:維護堆。過程:如果A[i]表示樹的某個結點,則A[2*i]是其左孩子,A[2*i+1]是其右孩子。接下來,比較三者大小挑選出最大元素的下標,存放於largest。然后。推斷(largest==i)嗎。若不滿足則進行元素交換。將大的元素上移。
此時,以A[largest]為根節點的子樹可能不滿足堆的性質,所以須要遞歸調用自身。
三、算法實現
上面介紹堆實現數組排序的原理,以下直接給出源代碼。
#include <stdlib.h> #include <stdio.h> #include <iostream> using namespace std; void Swap(int *x, int *y); void Max_heapify(int array[], int i, int heap_size); void Build_max_heap(int array[],int len); void Heapsort(int array[],int len); void Swap(int *x, int *y) { int temp; temp=*x; *x=*y; *y=temp; } void Max_heapify(int array[], int i, int heap_size) { int largest; int _left=2*i; int _right=2*i+1; if (_left<=heap_size && array[_left]>array[i]) { largest=_left; } else largest=i; if (_right<=heap_size && array[_right]>array[largest]) { largest=_right; } if (largest!=i) { Swap(&array[largest],&array[i]); Max_heapify(array,largest,heap_size); } } void Build_max_heap(int array[],int len) { int heap_size=len; for (int i=len/2; i>=1; i--) { Max_heapify(array,i,heap_size); } } void Heapsort(int array[],int len) { int heap_size=len; Build_max_heap(array,len); for (int i=len; i>=2; i--) { Swap(&array[1],&array[i]); heap_size--; Max_heapify(array,1,heap_size); } } void main() { int array[]={0,14,10,8,7,9,3,2,4,1}; int len=9; Heapsort(array,len); cout<<"heap sort result:\n"; for (int i=1; i<=len; i++) { cout<<array[i]<<" "; } cout<<endl; }
