堆排序是一种复杂度为O(nlog(n))的一种高效的排序,这里将展示最大堆的排序算法。
堆排序是将数组抽象化成为一个完全二叉树。这里对:A[10]={10,5,13,2,8,12,3,9,7,1}
抽象的二叉树结构如下:
1、下面三个节点是得到左子节点,右子节点,和父节点。
int left(int i) //返回左儿子
{
return 2 * i+1;
}
int right(int i) //返回右儿子
{
return 2 * i + 2;
}
int parent(int i) //返回父节点
{
return (i-1) / 2;
}
比如调用left(1),就是找A[1]的左子节点,就返回3
2、下面这个函数maxHeapIfy是将父节点的数和子节点的数对比,将最大的数移动到父节点上。在调换的子节点作为新的父节点实现相同的操作。如执行maxHeapIfy(A,0),先将右子节点的数13和父节点10进行交换:
被调换的子节点10进行递归调用maxHeapIfy(A,2),于是和左子节点的数进行交换:
代码如下:
void maxHeapIfy(int A[], int i,int n) //将i节点为根的堆中小的数依次上移,n表示堆中的数据个数
{
int l = left(i);
int r = right(i); //i的左儿子,i的右儿子
int largest; //记录父节点,子节点三个节点中最大值得位置
if (l < n&&A[l] > A[i])
largest = l;
else largest = i; //先找出A[i],和他的两个字节点最大值的位置
if (r < n&&A[r] > A[largest])
largest = r;
if (largest != i) //等于i不用做任何操作
{
swap(A[i],A[largest]);
maxHeapIfy(A, largest, n); //如果不是交换后的子节点不是以这个子节点为堆的最大值,递归调用。
}
return;
}
3、建立最大堆:
在这道题中,依次对8,2,12,1,0即是A[4],A[3],A[2],A[1],A[0]调用maxHeapIfy函数,就可以得到最大堆,即是从:
For i=(n-1)/2 to 0:
maxHeapIfy(A,i)
就可以实现最大堆。
void buildMaxHeap(int A[], int n) //建立最大堆
{
for (int i = n / 2-1; i >= 0; i--) //从(n/2-1)一次调用maxHeapIfy就可以得到最大堆
maxHeapIfy(A, i, n);
}
最后就是排序的过程,将第一个数踢出来,最后一个数放到第一个上,对剩下的数调用maxheapIfy,就可以得到降序的排列:
void heapSort(int A[], int n) //堆排序算法
{
buildMaxHeap(A, n); //先建立堆
cout << A[0] << endl;
for (int i = n-1; i >=0; i--)
{
swap(A[0], A[i]);
maxHeapIfy(A, 0, i);
cout << A[0] << endl;
}
}
主函数:
int array[10] = {10,5,13,2,8,12,3,9,7,1 };
heapSort(array, 10);
结果如下: