• 《算法导论》笔记 第6章 6.5优先级队列


    【笔记】

    一个最大优先队列支持以下操作:

    insert x:把元素x插入集合。

    maximum:返回集合中具有最大关键字的元素。

    extract-max:去掉并返回集合中具有最大关键字的元素。

    increase-key x k:将元素x的关键字增加到k,这里k值不能小于x的原关键字的值。

        Type heapMaximum() {
            return A[1];
        }
        Type heapExtractMax() {
            if (heapSize < 1) return 0;
            int max = A[1];
            A[1] = A[heapSize--];
            maxHeapify(1);
            return max;
        }
        void heapIncreaseKey(int i,Type key) {
            if (key < A[i]) return;
            A[i] = key;
            while (i>1 && A[parent(i)] < A[i]) {
                swap(A[i],A[parent(i)]);
                i = parent(i);
            }
        }
        void maxHeapInsert(Type key) {
            heapSize++;
            A[heapSize] = key;
            heapIncreaseKey(heapSize,key);
        }

    【练习】

    6.5-1 描述对堆 A = <15,13,9,5,12,8,7,4,0,6,2,1> 执行 HEAP_EXTRACT_MAX 操作的过程。

    记录返回值为15,将最后一个元素移动到根结点,堆变成 A = <1,13,9,5,12,8,7,4,0,6,2>,

    对根结点执行MAX_HEAPIFY,最终堆为 A = <13,12,9,5,6,8,7,4,0,1,2>





    6.5-2 描述在堆 A = <15,13,9,5,12,8,7,4,0,6,2,1> 上执行 MAX_HEAP_INSERT(A,10) 操作的过程。




    6.5-3 使用最小堆实现最小优先队列写出HEAP_MINIMUM,HEAP_EXTRACT_MIN,HEAP_DECREASE_KEY和MIN_HEAP_INSERT过程。

        Type heapMinimum() {
            return A[1];
        }
        Type heapExtractMin() {
            if (heapSize < 1) return 0;
            int min = A[1];
            A[1] = A[heapSize--];
            minHeapify(1);
            return min;
        }
        void heapDecreaseKey(int i,Type key) {
            if (key > A[i]) return;
            A[i] = key;
            while (i>1 && A[parent(i)] > A[i]) {
                swap(A[i],A[parent(i)]);
                i = parent(i);
            }
        }
        void minHeapInsert(Type key) {
            heapSize++;
            A[heapSize] = key;
            heapDecreaseKey(heapSize,key);
        }

    6.5-4 为什么我们在 MAX_HEAP_INSERT 先将关键字的值设置为无穷小,而后又将此关键值增大到所要求的值呢?

    不知道呀,直接设成所要求的值不行吗不行吗?> <


    6.5-5 使用以下的循环不变式来论证 HEAP_INCREASE_KEY 的正确性:

    在while循环的每次迭代之初,数组 A[1..heap-size[A]]满足最大堆性质,除了一个可能的例外:A[i]可能大于A[PARENT(i)]。

    初始化:在第1轮迭代之前。设结点i当前的值为 A[i],之前的值为 A'[i],可知 A[i] >= A'[i]。

    在结点i的值改变之前,数组A满足最大堆性质,因此A'[i] >= LEFT(i),A'[i] >= RIGHT(i)。

    因此A[i]>=LEFT(i),A[i]>=RIGHT(i)。由于只有结点i的数值增大过,A[i]可能大于A[PARENT(i)]。

    保持:若结点i大于父结点,则交换父结点与结点i,由最大堆的性质可知:A[PARENT(i)]>=A'[i]>=LEFT(i) and RIGHT(i)。

    因此A[PARENT(i)] >= A[LEFT(i)] and A[RIGHT(i)]且 A[PARENT(i)] <= A[i],A[i]>=A[PARENT(i)]>=A'[LEFT(PARENT(i))] and A'[RIGHT(PARENT(i))]。

    交换PARENT(i)与i可使最大堆的性质得到保持,除了一个可能的例外:A[i]可能大于新的父结点A[PARENT(i)]。为下一次迭代重新建立了循环不变式。

    终止:过程终止时,i为根结点或A[i]<=A[PARENT(i)]。此时数组满足最大堆性质,并且没有例外。


    6.5-6 说明如何使用优先级队列来实现一个先进先出队列,另请说明如何用优先级队列来实现栈。

    对插入的元素赋一个权值,优先队列通过比较权值来维护最大堆。

    队列:第一个插入的元素拥有最大的权值,随后插入的元素权值依次递减。此时,元素先进先出。

    栈:第一个插入的元素拥有最小的权值,随后插入的元素权值依次递增。此时,元素先进后出。


    6.5-7 HEAP-DELETE(A,i) 操作将节点i中的项从堆A中删去。对含n个元素的最大堆,请给出时间为O(logn)的HEAP_DELETE的实现。

        void heapDeleteMax(int i) {
            if (i<1||i>heapSize) return;
            A[i] = A[heapSize--];
            maxHeapify(i);
        }

    6.5-8 请给出一个时间为O(nlogk)、用来将k个已排序链表合并为一个排序链表的算法。此处n为所有输入链表中元素的总数。

    1、将k个链表的第一个元素插入堆中。

    2、取出堆中的最小元素,若该元素所在的链表不为空,将其下一个元素插入到堆中。重复这一步操作直到取出堆中所有元素。

    复杂度证明:

    优先队列中的元素总数不会超过k,插入一个元素的复杂度为O(logk),弹出队首元素复杂度为O(logk)。

    n个元素各入队出队一次,因此总复杂度为O(n)*(O(logk)+O(logk)) = O(nlogk)




  • 相关阅读:
    APP开发关于缓存
    SlidingMenu+Fragment实现当前最流行的侧滑
    深入理解dp px density
    HDU1847--Good Luck in CET-4 Everybody!(SG函数)
    【转】博弈论——acm
    HDU1846--Brave Game(巴什博弈)
    HDU2179--pi(麦金公式)
    HDU1026--Ignatius and the Princess I(BFS记录路径)
    HDU1237--简单计算器(栈的应用)
    HDU3398—String-(组合数)
  • 原文地址:https://www.cnblogs.com/cyendra/p/3681629.html
Copyright © 2020-2023  润新知