1. 基本思想
由于堆的性质为:
(1)完全二叉树
(2)树的父节点值小于其子节点值。(小堆)
(3)树的父节点值大于其子节点值。(大堆)
利用大堆(小堆)的性质,将数组建立成一个堆结构,再依次对堆进行删除堆顶元素的操作,此时堆中最大(最小)元素将被依次取出。要想进行升序排序则建立大堆,要想进行降序排序则建立小堆。
2. 整体思路分析(以建立大堆升序排序为例)
根据基本思想:1.先根据数组创建需要的堆 2.对堆进行删除操作,删除操作即删除堆顶元素
2.1 如何利用数组建立堆结构
基本思路:依次将数组中的元素放在堆数组的末尾,采用上浮式调整。即子节点与其父节点进行比较,若该子节点值大于其父节点值时,交换两个节点值,依次不断向上调整,直到该子节点值满足堆的要求或者来到堆根节点的子节点处表示调整结束。
void HeapCreate(int array[],size_t size)
{
//从后往前每一个元素进行调整
size_t bound=0;
for(;bound<size;bound++)
{
AdjustUp(array,bound,bound);
}
}
void AdjustUp(int array[],size_t size,size_t index)
{
size_t child=index;
size_t parent=(child-1)/2;
while(child>0)
{
if(array[parent]<array[child])
{
Swap(&array[parent],&array[child]);
}
else
{
break;
}
child=parent;
parent=(child-1)/2;
}
}
2.2 删除堆操作
基本思路:删除堆操作是删除堆顶元素,将堆顶元素与堆最后一个元素交换表示对堆进行了一次删除,此时删除操作破坏了堆的结构,故需要进行调整,调整即需要依次从前往后调整堆顶元素的位置,直到满足堆结构为止。
void HeapPop(int array[],size_t heap_size)
{
//先交换第一个元素和最后一个元素的值
Swap(&array[0],&array[heap_size-1]);
//再对第一个元素进行向下调整
AdjustDown(array,heap_size-1,0);
}
void AdjustDown(int array[],size_t heap_size,size_t index)
{
size_t parent=index;
size_t child=2*parent+1;
while(child<heap_size)
{
if(child+1<heap_size&&array[child]<array[child+1])
{
child=child+1;
}
if(array[parent]<array[child])
{
Swap(&array[parent],&array[child]);
}
parent=child;
child=2*parent+1;
}
}
3. 代码实现堆排序(代码中有详细解释)
//0.交换两个数的值
void Swap(int* x,int* y)
{
int tmp=*x;
*x=*y;
*y=tmp;
}
//堆排序
void HeapSort(int array[],size_t size)
{
//当size<=1时,不需要排序直接return
if(size<=1)
return;
//1.基于数组建立堆
HeapCreate(array,size);
//2.循环删除堆元素
size_t i=0;
for(;i<size;i++)
{
//size-i表示删除一个堆元素之后,堆的大小就-1
HeapPop(array,size-i);
}
}
//根据数组创建堆
void HeapCreate(int array[],size_t size)
{
//从后往前每一个元素进行调整
size_t bound=0;
for(;bound<size;bound++)
{
AdjustUp(array,bound,bound);
}
}
void AdjustUp(int array[],size_t size,size_t index)
{
size_t child=index;
size_t parent=(child-1)/2;
while(child>0)
{
if(array[parent]<array[child])
{
Swap(&array[parent],&array[child]);
}
else
{
break;
}
child=parent;
parent=(child-1)/2;
}
}
//删除堆操作
void HeapPop(int array[],size_t heap_size)
{
//先交换第一个元素和最后一个元素的值
Swap(&array[0],&array[heap_size-1]);
//再对第一个元素进行向下调整
AdjustDown(array,heap_size-1,0);
}
void AdjustDown(int array[],size_t heap_size,size_t index)
{
size_t parent=index;
size_t child=2*parent+1;
while(child<heap_size)
{
if(child+1<heap_size&&array[child]<array[child+1])
{
child=child+1;
}
if(array[parent]<array[child])
{
Swap(&array[parent],&array[child]);
}
parent=child;
child=2*parent+1;
}
}