CLRS 6.5优先队列

来源:互联网 发布:pdf分割小软件 编辑:程序博客网 时间:2024/06/05 06:12

6.5-1
这里写图片描述

6.5-2
这里写图片描述

6.5-3
伪代码参考书上的最大堆的最大优先队列。下面给出实际代码(包括最大最小堆和最大最小优先队列)。

#include <iostream>#include<vector>#include<limits>#include <stdexcept>using namespace std;#define PARENT(i) ((i-1)/2)#define LEFT(i) (2*i+1)#define RIGHT(i) (2*i+2)void max_heapify(vector<int> &heap, int heap_size, int i){    int l = LEFT(i);    int r = RIGHT(i);    int larger;    if (l < heap_size && heap[l] > heap[i])        larger = l;    else larger = i;    if (r < heap_size && heap[r] > heap[larger])        larger = r;    if (larger != i)    {        swap(heap[larger], heap[i]);        max_heapify(heap, heap_size,larger);    }}void build_max_heap(vector<int> &heap){    for (int i = PARENT(heap.size() - 1); i >= 0; --i)        max_heapify(heap, heap.size(), i);}void max_heap_sort(vector<int> &heap){    build_max_heap(heap);    for (int i = heap.size() - 1; i > 0; --i)    {        swap(heap[i], heap[0]);        max_heapify(heap, i, 0);    }}int heap_maximum(vector<int> &heap){    return heap[0];}int heap_extract_max(vector<int> &heap){    if (heap.empty())        throw runtime_error("Extract on empty heap");    int ret = heap[0];    heap[0] = heap[heap.size() - 1];    heap.pop_back();    max_heapify(heap, heap.size(), 0);    return ret;}void heap_increase_key(vector<int> &heap, int i, int key){    if (heap[i] > key)        throw invalid_argument("New key is smaller than current key");    /*heap[i] = key;    while (i > 0 && heap[i] > heap[PARENT(i)])    {        swap(heap[i], heap[PARENT(i)]);        i = PARENT(i);    }*/    while (i > 0 && key > heap[PARENT(i)])//更改书中代码,详见练习6.5-6    {        heap[i] = heap[PARENT(i)];        i = PARENT(i);    }    heap[i] = key;}void max_heap_insert(vector<int> &heap, int key){    heap.push_back(INT_MIN);    heap_increase_key(heap, heap.size() - 1, key);}void min_heapify(vector<int> &heap, int heap_size, int i){    int smaller;    while (true)    {        int l = LEFT(i);        int r = RIGHT(i);        if (l < heap_size && heap[l] < heap[i])            smaller = l;        else smaller = i;        if (r < heap_size && heap[r] < heap[smaller])            smaller = r;        if (smaller != i)        {            swap(heap[smaller], heap[i]);            i = smaller;        }        else break;    }}void build_min_heap(vector<int> &heap){    for (int i = PARENT(heap.size() - 1); i >= 0; --i)        min_heapify(heap, heap.size(), i);}void min_heap_sort(vector<int> &heap){    build_min_heap(heap);    for (int i = heap.size() - 1; i > 0; --i)    {        swap(heap[0], heap[i]);        min_heapify(heap, i, 0);    }}int heap_minimum(vector<int> &heap){    return heap[0];}int heap_extract_min(vector<int> &heap){    if (heap.empty())        throw runtime_error("Extract on empty heap");    int ret = heap[0];    heap[0] = heap[heap.size() - 1];    heap.pop_back();    min_heapify(heap, heap.size(), 0);    return ret;}void heap_decrease_key(vector<int> &heap, int i, int key){    if (heap[i] < key)        throw invalid_argument("New key is larger than current key");    heap[i] = key;    while (i > 0 && heap[i] < heap[PARENT(i)])    {        swap(heap[i], heap[PARENT(i)]);        i = PARENT(i);    }}void min_heap_insert(vector<int> &heap, int heap_size, int key){    heap.push_back(INT_MAX);    heap_decrease_key(heap, heap.size() - 1, key);}int main(){    vector<int> array = { 13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7 };    min_heap_sort(array);    for (auto n : array)        cout << n << ' ';    cout << endl;    cout << heap_minimum(array) << endl;    cout << heap_extract_min(array) << endl;    for (auto n : array)        cout << n << ' ';    cout << endl;    heap_decrease_key(array, 5, -100);    for (auto n : array)        cout << n << ' ';    cout << endl;    min_heap_insert(array, 15, 2);    for (auto n : array)        cout << n << ' ';    cout << endl;    return 0;}

6.5-4
为了保证 HEAP_INCREASE_KEY 中原先的关键字小于将要被增加的值。

6.5-5
初始化:没增值之前满足最大堆性质,A[i] 增加之后唯一破坏性质的只可能是 A[i]>A[PARENT(i)]
保持:交换 A[i]A[PARENT(i)] 之后,唯一破坏性质的只可能是 A[PARENT(i)]>A[PARENT(PARENT(i))],改变 i=PARENT(i) 保持循环不变量;
终止:当循环终止时 i=1 或者 A[i]<A[PARENT(i)],当 i=1A[PARENT(i)] 不存在,而 A[i]<A[PARENT(i)] 时不破坏堆的性质。

6.5-6
修改 while 条件判断,同时将原 HEAP_INCREASE_KEY 的第五行改为 A[i] = A[PARENT(i)]。然后添加第七行 A[i] = key 即可。可参考6.5-3中的 HEAP_INCREASE_KEY 代码。

6.5-7
假如我们使用的是最大优先队列,对于先进先出队列,我们将第一个关键字设为最大,每次插入的时候将关键字依次减小。栈则相反。

6.5-8
伪代码如下:

HEAP-DELETE(A, i):  A[i] = A[A.heap-size]  A.heap-size -= 1  MAX-HEAPIFY(A, i)

6.5-9
1) 在每一个链表中取出第一个值,然后把它们放在一个大小为 K 的数组里,然后把这个数组建成一个最小堆。此步骤的时间复杂度为 O(k)
2) 取出堆中的最小值,然后把该最小值所处的链表的下一个值放入堆中并调整堆。如果链表中有一个已经为空(元素已经都被取出),则改变堆的大小。此步骤的时间复杂度为O(lgK)
3) 不断的重复步骤二,直到所有的链表都为空。

0 0
原创粉丝点击