算法导论——最大序列堆与堆排序C语言实现

 第六章

堆排序

堆可以被近似看成一个近似完全二叉树
以结点数为10的树为例  

给定一个节点下标为i,则其父,子节点分别为
parent(i)   
return i/2   //父结点
left(i)
return 2*i   //左子结点
right(i)
return 2*i+1  //右子结点


如 i= 2则其左子结点为4 右子节点为5 父节点为1
二叉堆可分为两种形式

最大堆 所有结点父结点要大于等于其自身 
最小堆 所有结点父结点都要小于其自身
维护堆的性质
在输入新的数据时可能会导致堆违背最大堆性质通过调用一个函数,使以新的树位
根节点的子树重新遵循最大堆的性质。
原书伪代码

maxheap(A,i)
l = left(i)    //找出左右子结点的编号
r = right(i)
if l <= A.heap-size and A[l] > A[i] //判断i与其左右子结点大小关系,并确定最大结点的编号
   largest = l;
else largest = i
if r <= A.heap-size and A[r] > A[largest]
   largest = r
if largest != i    //如果最大结点不是i则交换i与其子结点的值,使其满足最大子树堆
   exchange A[i] with A[largest]
   maxheap(A,largest) //调换之后其子节点也可能不满足最大堆性质,所以要逐层递归调用

建堆
在拥有维护堆性质工具后,我们可以进行最大堆的建立。

我们要对除叶子结点(即度为0的结点,无子树)的其他结点调用maxheap以维护
最大堆的性质。

n/2+1 to n 中的元素都是叶子结点
所以对1 to n/2所有结点调用维护函数

原书伪代码

buildmaxheap
A.heap-size = A.length //实际元素数量  数组元素数量
for i = A.length/2 down to 1
    maxheap(A,i)

利用最大堆我们可以进行排序,根据最大堆的性质,根结点总是最大的结点,所以
只要一次比较根节点,即可进行排序,并在过程中不断维护最大堆性质,以满足根节点最大,

注意 排过序的结点不应再被维护,所以应该将实际元素个数缩小
原书伪代码

heapsort(A)
buildmaxheap(A)
for i = A.length down to 2
    exchange A[1] with A[i]
    A.heap-size = A.heap-size-1
    maxheap(A,1)


C语言实现堆排序

#include<stdio.h>
int truesize = 10; //实际堆中的元素(此程序堆中元素为10个等于数组元素数量
int parent(int i) //计算关系结点编号
{
return i/2;
}
int left(int i)
{
return 2*i;
}

int right(int i)
{
return 2*i+1;
}

void maxheap(int a[],int i) //维护最大堆性质
{ int largest;  //储存最大结点编号
int l;     //左结点
int r;     //右 
int exchange;

l = left(i);
r = right(i);
if(a[l-1] > a[i-1]&& l <= truesize) //注意 C语言数组下标应该将i-1
largest = l;
else
largest = i;
if(a[r-1] > a[largest-1]&&r <= truesize)
largest = r;
if(largest != i)
{
exchange = a[largest-1];
a[largest-1] = a[i-1];
a[i-1] = exchange;
maxheap(a,largest);  //逐层维护
}

}

void buildmaxheap(int a[])  //建立最大堆
{
int n = 10;
int i;
for( i = n/2;i > 0;i--)
{

maxheap(a,i);

}

}

void heapsort(int a[])  //堆排序
{
int i = 10;
int exchange;
for(;i>1;i--)
{ 
exchange = a[0];
a[0] = a[i - 1];
a[i - 1] = exchange;
truesize--;
maxheap(a,1);
}

}
int main()
{ 
int a[10];
int n,i;
printf("scanf------------------\n");
for(i = 0;i < 10;i++) //输入堆中元素
scanf("%d",&a[i]);

printf("maxheap------------------\n");

buildmaxheap(a);    //建立最大堆
for(i = 0;i < 10;i++)
printf("%d ",a[i]);  //输出
heapsort(a);       //堆排序
printf("\nresult------------------\n");
for(i = 0;i < 10;i++)
printf("%d ",a[i]);   //输出结果

return 0;
}

运行样例

猜你喜欢

转载自blog.csdn.net/jazrynwong/article/details/79766386
今日推荐