学习《算法导论》第六章 堆排序 总结二

来源:互联网 发布:韩国网络爆红65g 编辑:程序博客网 时间:2024/05/21 08:58

学习《算法导论》第六章 堆排序 总结二

在《堆排序_学习总结一》中学习了堆的概念, 最大堆的性质, 以及如何保持最大堆性质、如何建立堆这两个的算法. 最后就是基于这两个算法学习了堆排序的算法. 接下来继续学习几个关于堆的算法.
堆作为一种数据结构, 也有一些基本操作:求堆中的最大值、在堆中插入关键字key、删除堆中的最大值、将堆中某个关键字增加到新的key等.下面分别学习这些算法. 以及由这些算法实现的最大优先级队列.

返回堆中的最大值

这个简单, 堆中的最大值就是根结点. 算法如下:

HEAP-MAXIMUM(A)1    return A[1]

删除堆中的最大值,即删除根结点

删除了根结点, 那么堆的性质就被破坏. 这里调用MAX-HEAPIFY过程来保持堆的性质. 算法如下:

    HEAP-EXTRACT-MAX(A)    1    if heapsize[A] < 1    2       then error "heap underflow"    3    max <--- A[1]    4    A[1] <--- A[heapsize[A]]    5    heapsize[A]--    6    MAX-HEAPIFY(A, 1)    7    return max

删除堆中任一结点的算法类似. 但是往往都是要删除堆的最大值(或最小堆的最小值).

将堆中某关键字增加到key

该关键字增加到key后, 堆的性质有可能会破坏, 所以要检查堆的性质是否被破坏. 但是这里并没有直接调用MAX-HEAPIFY过程来保持堆的性质, 而是采用了类似于它的过程. 算法如下:

    HEAP-INCREASE-KEY(A, i, key)    1    if key < A[i]    2       then error "new key is smaller than current key"    3    A[i] <--- key    4    while i > 1 and A[PARENT(i)] < A[i]    5        do exchange A[i] <-> A[PARENT(i)]    6           i <--- PARENT(i)

该算法主要是第4步到第6步. 运行时间为:O(lg n)

在堆中插入关键字key

在堆中插入新的元素key, 具体算法如下:

    MAX-HEAP-INSERT(A, key)    1    heapsize[A]++    2    A[heapsize[A]] <--- 0    3    HEAP-INCREASE-KEY(A, heapsize[A], key)

优先级队列

这里的优先级队列正是由堆来实现的, 优先级队列分为:最大优先级队列和最小优先级队列. 下面讨论的是用最大堆来实现最大优先级队列. 最大优先级队列支持以下几个操作:
INSERT(S, x)
MAXIMUM(S)
EXTRACT-MAX(S)
INCREASE-KEY(S, x, k)
而这四种操作正好对应上面的堆的操作.
最大优先级队列的一个应用就是在一台分时计算机上进行作业调度.

上述算法的代码实现

// 返回堆中的最大值int MaximumHeap (int* Heap){    return Heap[0];}// 删除堆中的最大值,即删除根结点int ExtractMaxInHeap (int* Heap, int HeapLength){    if (0 == HeapLength)    {        printf ("heap underflow!\n");        return -1;    }    int Max = Heap[0];    // 将最后一个结点作为根结点, 保持完全二叉树    Heap[0] = Heap[HeapLength - 1];    HeapLength--;    // 保持最大堆的性质    MaxHeapify(Heap, HeapLength, 1);    return Max;}// 将堆中某关键字增加到keyvoid IncreaseKeyInHeap (int* Heap, int HeapNodeId, int Key){    if (Key < Heap[HeapNodeId - 1])    {        printf("New Key Is Smaller Than Current Key!\n");        return;    }    Heap[HeapNodeId - 1] = Key;    // 判断该结点的值增加到Key后, 堆的性质是否改变    while ((HeapNodeId > 1) && (Heap[PARENT[HeapNodeId] - 1] < Heap[HeapNodeId - 1]))    {        swap(Heap + PARENT[HeapNodeId] - 1, Heap + HeapNodeId - 1);        HeapNodeId = PARENT[HeapNodeId];    }    return;}// 在堆中插入关键字keyvoid InsertInHeap (int* Heap, int HeapLength, int Key){    HeapLength++;    Heap[HeapLength - 1] = -10000;    // 将堆中某关键字增加到key    IncreaseKeyInHeap(Heap, HeapLength, Key);    return;}
0 0