C语言实现二叉堆BuildHeap操作

优先队列(二叉堆)BuildHeap操作

B u i l d H e a p ( H ) BuildHeap(H) 操作把 N N 个关键字作为输入并把它们放入空堆中。显然,这可以使用 N N 个相继的 I n s e r t Insert 操作来完成。由于每个 I n s e r t Insert 将花费 O ( 1 ) O(1) 平均时间以及 O ( log N ) O(\log N) 的最坏情形时间,因此该算法的总的运行时间则是 O ( N ) O(N) 的平均时间而不是 O ( N log N ) O(N \log N) 最坏情形时间。
一般的算法是将 N N 个关键字以任意顺序放入树中,保持 结构性 。此时,如果 P e r c o l a t e D o w n ( i ) PercolateDown(i) 从节点 i i 下滤,那么执行下代码中的算法创建一颗具有堆序的树( h e a p o r d e r e d t r e e heap-ordered-tree )。

二叉堆有两个性质:结构性质和堆序性质。

for(i = N / 2; i > 0; i--)
	PercolateDown(i);

定理

包含 2 b + 1 1 2^{b+1}-1 个节点高为 b b 理想二叉树(perfect binary tree)(也叫完全二叉树)的节点的高度的和为 2 b + 1 1 ( b + 1 ) 2^{b+1}-1-(b+1)

代码

PriorityQueue BuildHeap(ElementType *Elements, int N)
{
    int i;
    PriorityQueue H;
    H = Initialize(N);

    for (i = 1; i <= N; i++)
        H->Elements[i] = Elements[i - 1];
    H->Size = N;

    for (i = N / 2; i > 0; i--)
        PercolateDown(i, H);

    return H;
}

void PercolateDown(int i, PriorityQueue H)
{
    int MinSon, Min;
    ElementType Tmp;

    if (i <= H->Size / 2)
    {
        MinSon = i * 2 + 1 <= H->Size && H->Elements[i * 2] > H->Elements[i * 2 + 1] ? i * 2 + 1 : i * 2;
        Min = H->Elements[i] < H->Elements[MinSon] ? i : MinSon;
        Tmp = H->Elements[i];
        H->Elements[i] = H->Elements[MinSon];
        H->Elements[MinSon] = Tmp;
        PercolateDown(MinSon, H);
    }
}

另一种线性时间实现方法

把每个元素当作是单节点左式堆,把所有这些堆放到一个队列中。之后,让两个堆出队,合并它们,再将合并结果入队,直到队列中只有一个堆为止。

该算法在最坏情形下为 O ( N ) O(N)

此方法生成的堆更“左”。

发布了32 篇原创文章 · 获赞 18 · 访问量 3236

猜你喜欢

转载自blog.csdn.net/u011714517/article/details/104137253
今日推荐