一直以来都不敢去学习了解堆排序,无形中自己产生对该算法的畏惧心理。今天有幸弄通,特来祭奠!看来世事,只要敢行,就一定行!
概述
堆排序使用数据结构中的堆结构,通过建立堆,然后循环调整堆,完成排序过程。
基础
首先要了解完全二叉树的概念,将堆分为大根堆和小根堆。大根堆用于维护非降序序列(也就是升序排列)。
对于完全二叉树必须记住的一个口诀:
1)父节点i的左子节点位置:2*i + 1
2)父节点i的右子节点位置:2*i + 2
3)子节点i的父节点位置:floor((i - 1) / 2)
上面公式都也不需要死机硬背,只需要知道树结构的父子位置关系是2^h关系即可。
过程
首先,需要创建堆。
void CreateHeap(int A[], int hLen)
{
int begin = hLen >> 2 - 1;
for ( int i = begin; i >= 0; i-- )
{
AdjustHeap(A, hLen, i);
}
}
其次,调整堆。
void AdjustHeap(int A[], int hLen, int i)
{
int left = LeftChildIndex(i);
int right = RightChildIndex(i);
int largest = i;
while (left < hLen && right < hLen)
{
if( left < hLen && A[largest] < A[left] )
{
largest = left;
}
if( right < hLen && A[largest] < A[right] )
{
largest = right;
}
if( largest != i )
{
int temp = A[largest];// 交换最大值与父节点位置
A[largest] = A[i];
A[i] = temp;
i = largest;// 调整父节点位置
left = LeftChildIndex(i);// 调整子节点位置
right = RightChildIndex(i);
}else{
break;
}
}
}
最后,取调整堆后的堆顶元素,输出排序序列。
void HeapSort(int A[], int aLen)
{
int hLen = aLen;
CreateHeap(A,hLen);
while (hLen > 1)
{
int temp = A[hLen - 1];
A[hLen - 1] = A[0];
A[0] = temp;
hLen --;
AdjustHeap(A,hLen,0);
}
}
具体过程如下图所示,下图为创建一个大根堆过程。
堆排序,获取排序序列:
int LeftChildIndex(int cur)
{
return (cur << 1) + 1;
}
int RightChildIndex(int cur)
{
return (cur << 1) + 2;
}
int ParentIndex(int cur)
{
return (cur - 1) >> 1;
}