(二插)堆是一个数组,可以被看成一个近似的完全二叉树。
树的根节点是A[1]
第一步:
给定一个节点的下标i,我们可以计算得到它的 父结点和左右孩子的下标:
int Parent(int i)
{
return floor(i / 2.0);
}
int Left(int i)
{
return 2 * i;
}
int Right(int i)
{
return 2 * i + 1;
}最大堆性质:除了根以外的所有节点i都满足:
A[Parent(i)] >= A[i]
最小堆性质:除了根以外的所有节点i都满足:
A[Parent(i)] <= A[i]
以下我们讨论最大堆。
第二步:
我们需要一个过程来维护堆的性质:
//使二叉树满足最大堆性质
void Max_Heapify(int* A, int i)
{
int l = Left(i);
int r = Right(i);
int largest = 0;
if(l <= heap_size && A[l] > A[i])
largest = l;
else
largest = i;
if(r <= heap_size && A[r] > A[largest])
largest = r;
if(largest != i)
{
int temp = A[i];
A[i] = A[largest];
A[largest] = temp;
Max_Heapify(A,largest);
}
}我们从A[i]、A[Left(i)]、A[Right(i)]中选出最大的,并将其下标存在largest中。
如果非叶子结点A[i]是最大的,那么以i为根结点的子树已是最大堆,过程结束。
否则,最大的是i的某个孩子,那么,交换A[i]和A[largest]的值。从而i和其孩子都满足最大堆的性质(也就是递归,因为在交换后,下标为largest的结点的值为原来的A[i],这样可能导致以该结点的子树违反最大堆的性质。因此,需要递归调用Max_Heapify)。
第三步:
建堆:
我们先利用Max_Heapify过程把数组转换为最大堆。
//建堆
void Build_Max_Heap(int* A)
{
heap_size = length;
for(int i = floor(length / 2.0); i >=1; i--)
{
Max_Heapify(A, i);
}
}
第四步:
堆排序算法:
void Heap_Sort(int* A)
{
Build_Max_Heap(A);
printf("建立最大堆:");
for(int i=1;i<=length;i++)
printf("%d ", A[i]);
printf("\n");
for(int i = length;i >= 2; i--)
{
int temp = A[1];
A[1] = A[i];
A[i] = temp;
heap_size = heap_size - 1;
Max_Heapify(A, 1);
printf("第%d次排序:", ++iter);
for(int i=1;i<=length;i++)
printf("%d ", A[i]);
printf("\n");
}
}
完整程序示例代码:
#include "stdafx.h"
#include <math.h>
int length = 10;
int heap_size;
int A[11] = {0,16,14,10,8,7,9,3,2,4,1};
int iter = 0;
int Parent(int i)
{
return floor(i / 2.0);
}
int Left(int i)
{
return 2 * i;
}
int Right(int i)
{
return 2 * i + 1;
}
//使二叉树满足最大堆性质
void Max_Heapify(int* A, int i)
{
int l = Left(i);
int r = Right(i);
int largest = 0;
if(l <= heap_size && A[l] > A[i])
largest = l;
else
largest = i;
if(r <= heap_size && A[r] > A[largest])
largest = r;
if(largest != i)
{
int temp = A[i];
A[i] = A[largest];
A[largest] = temp;
Max_Heapify(A,largest);
}
}
//建堆
void Build_Max_Heap(int* A)
{
heap_size = length;
for(int i = floor(length / 2.0); i >=1; i--)
{
Max_Heapify(A, i);
}
}
void Heap_Sort(int* A)
{
Build_Max_Heap(A);
printf("建立最大堆:");
for(int i=1;i<=length;i++)
printf("%d ", A[i]);
printf("\n");
for(int i = length;i >= 2; i--)
{
int temp = A[1];
A[1] = A[i];
A[i] = temp;
heap_size = heap_size - 1;
Max_Heapify(A, 1);
printf("第%d次排序:", ++iter);
for(int i=1;i<=length;i++)
printf("%d ", A[i]);
printf("\n");
}
}
int _tmain(int argc, _TCHAR* argv[])
{
Heap_Sort(A);
printf("最后排序结果:");
for(int i=1;i<=length;i++)
printf("%d ", A[i]);
getchar();
return 0;
}结果展示:
本文介绍了C++实现堆排序算法的过程,包括最大堆的性质、如何维护堆的性质、建堆步骤以及堆排序算法的完整代码示例,重点阐述了分治法和递归在算法中的应用。

被折叠的 条评论
为什么被折叠?



