您的位置:首页 > 其它

学习笔记_堆

2015-12-27 17:29 211 查看
Heap:堆

堆是一种建立在树上的结构,是一种完全二叉树型的数据结构,目前了解到的应用是堆排序,然后用于实现优先队列。堆的特点是,子结点一定比父结点大或者小于父结点。其中,所有子结点都小于父结点的堆是最大二叉堆,子结点小于父结点的是最小二叉堆。

堆的核心是heapify,维护堆合法性的算法;后续谈到的建立堆,堆排序,堆中插入元素,删除元素都离不开维护堆合法性。所以在一开始打算谈一下如何维护堆的合法性。

这里用到数组来模拟二叉堆。为所有的结点编号。那么任取一个结点,若该结点有子结点,则该结点的左子结点编号为父结点编号*2,右结点为其父结点编号*2+1。那么维护堆合法性就需要将选定结点与其子结点进行比较。以最大二叉堆为例,选出父结点,子结点中值最大的点,若该点不为父结点,则将该结点与父结点交换,并考虑交换后原交换结点处的合法性。代码如下:

void heapify(int *A,int i,int n)
{
int max=i;
int l,r;
l=i*2; r=i*2+1;
if (A[m]<A[l]&&l<n)
m=l;
if (A[m]<A[r]&&r<n)
m=r;
if (m!=i)
{
swap(A[m],A[i]);
heapify(A,m,n);
}
}
基于heapify可以实现堆的其他功能。接下来谈建堆,此处以建立最大堆为例。

void build_max_h(int *A,int n)
{
for (int i=n/2;i>=1;i--)
heapify(A,i,n);
}


在一个二叉堆中对于高度为h的堆,其第i层最多含有2^(i-1)个结点,且堆是一种完全二叉树型的数据结构。那么,h层的结点编号为2^(h-1)~2^h-1。一共有n个结点,那么n/2~n为叶子结点。对于这些结点可以看做仅含一个结点的子堆。那么从他们的父结点开始向上层考察堆的合法性,每次可以保证,从考察结点开始的子堆在合法性维护结束后,该子结点一定是合法的。那么考察到最顶层后,整个堆就是合法的。

堆排序是一种基于堆结构的排序方法。核心思想是取出堆顶元素,与最后一个元素交换位置,将元素数量减一,然后维护堆的合法性。

void heapsort(int *A,int &n
{
for (int i=n;i>=2;i--)
{
swap(A[1],A[i]);
n--;
heapify(A,1,n);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: