Chapter 9-MaxHeap

Please indicate the source if you want to reprint: http://blog.csdn.net/gaoxiangnumber1.
优先队列(priority queue) 是0个或多个元素的集合,每个元素都有一个优先权或值,对优先队列执行的操作有 1) 查找;2) 插入一个新元素; 3) 删除。在最小优先队列( min priority queue)中,查找操作用来搜索优先权最小的元素,删除操作用来删除该元素;对于最大优先队列(max priority queue),查找操作用来搜索优先权最大的元素,删除操作用来删除该元素。优先权队列中的元素可以有相同的优先权,查找与删除操作可根据任意优先权进行。
[最大树(最小树) ] 是每个节点的值都大于(小于)或等于其子节点(如果有的话)值的树。最大树或最小树节点的子节点个数可以大于 2。

[最大堆(最小堆) ] 是最大(最小)的完全二叉树。
完全二叉树的相关性质(设该完全二叉树共有n个节点):
设某父节点的编号为i(从1开始), 1≤i≤n。则:
1) 当i =1时,该元素为二叉树的根。若 i > 1,则该元素父节点的编号为 i /2。
2) 当2i >n时,该元素无左孩子。否则,其左孩子的编号为 2i。
3) 若2i +1>n,该元素无右孩子。否则,其右孩子编号为 2i +1。
该树的高度为深度为log2(n+1)
插入:
图9-3a 给出了一个具有 5个元素的最大堆。由于堆是完全二叉树,当加入一个元素形成6元素堆时,其结构必如 9-3b 所示。
如果插入元素的值为 1,则插入后该元素成为 2的左孩子。
若新元素的值为 5,则该元素不能成为 2的左孩子,应把2下移为左孩子(如图 9 - 3c所示),同时还得决定在最大堆中 5是否占据 2原来的位置。由于父元素 20大于等于新插入的元素 5,因此可以在原 2所在位置插入新的元素。
假设新元素的值为21而不是5,这时,同图 9-3c 一样,把 2下移为左孩子,由于 21比父元素值大,所以 21不能插入原来 2所在位置,因此把 20移到它的右孩子所在位置, 21插入堆的根节点(如图 9 - 3 d所示)。

插入策略从叶到根只有单一路径,每一层的工作需耗时O( 1 ),因此实现此策略的时间复杂性为O(height) = O (log2(n+1)), n为最大堆中的元素个数。

删除

从最大堆中删除一个元素时,该元素从堆的根部移出。
对图 9-3d 的最大堆进行删除操作即是移去元素 21,因此最大堆只剩下五个元素。此时,图 9-3d 中的二叉树需要重新构造,以便仍然为完全二叉树。为此可以移动位置 6中的元素,即2。这样就得到了正确的结构(如图9-4 a所示)。如果 2直接插入根节点,得到的二叉树不是最大树,根节点的元素应为 2、根的左孩子、根的右孩子三者中的最大值。这个值是 20,它被移到根节点,因此在位置 3形成一个空位,由于这个位置没有孩子节点, 2可以插入,最后形成的最大堆如图9-3a 所示。
现在假设要删除20,在删除之后,堆的二叉树结构如图 9-4b 所示,为得到这个结构,10从位置5移出,如果将 10放在根节点,结果并不是最大堆。把根节点的两个孩子( 15和2)中较大的一个移到根节点。假设将10插入位置2,结果仍不是最大堆。因此将14上移,10插入到位置4,最后结果如图9-4c 所示。
删除策略产生了一条从堆的根节点到叶节点的单一路径,每层工作需耗时O(1),时间复杂性为 O(height) = O (log2(n+1)), n为最大堆中的元素个数
Review:
MaxHeap.h
Test.cc

MaxHeap.h


#ifndef MAXHEAP_H_INCLUDED
#define MAXHEAP_H_INCLUDED

using std::cout;
using std::cin;
using std::endl;

template<typename T>
class MaxHeap
{
public:
    MaxHeap(): current_size_(0), max_size_(0), heap_(0) {}  // default constructor
    ~MaxHeap();  // destructor
    void CreateMaxHeap();  // create a max heap
    void Insert(const T &element);  // insert element into max heap
    void Delete();  // delete the max element from heap
    void Output();  // print max heap's contents

private:
    // current_size_ is the amount of elements now
    // max_size_ is the max amount of all elements the heap can hold
    int current_size_, max_size_;
    T *heap_;
};

template<typename T>
MaxHeap<T>::~MaxHeap()
{
    delete heap_;
    heap_ = 0;  // avoid dangling pointer
    current_size_ = 0;  // very important: avoid access invalid memory
    max_size_ = 0;
}

template<typename T>
void MaxHeap<T>::CreateMaxHeap()
{
    cout << "Please input heap's max size and current size:\n";
    int max_size, current_size;
    cin >> max_size >> current_size;
    max_size_ = max_size;
    heap_ = new T [max_size_ + 1];  // element index begin from 1, so we need one more element space
    cout << "Please input " << current_size << " elements:\n";
    for(int index = 1; index <= current_size; index++)
    {
        T element;
        cin >> element;
        Insert(element);
    }
    Output();
}

template<typename T>
void MaxHeap<T>::Insert(const T &element)
{
    if(current_size_ < max_size_)  // if there is free memory in heap
    {
        int position = ++current_size_;  // we should insert element into heap[position]
        // if element is bigger than it's parent node's value
        // position != 1: indicate the element has parent node
        while(position != 1 && element > heap_[position/2])
        {
            heap_[position] = heap_[position/2];  // move it's parent node down
            position = position / 2;  // move element to parent node's position
        }
        heap_[position] = element;  // insert element
    }
}

template<typename T>
void MaxHeap<T>::Delete()
{
    if(current_size_ != 0)  // if heap is not empty
    {
        T last_element = heap_[current_size_--];  // get the last element from heap and decrement size
        // we will insert last_element into heap[empty_position]
        // heap[max_child_position] is the bigger child node of parent node heap[empty_position]
        int empty_position = 1, max_child_position = 2;
        while(max_child_position <= current_size_)
        {
            // check whether heap_[max_child_position] is the bigger child node
            if(max_child_position < current_size_ &&
                heap_[max_child_position] < heap_[max_child_position + 1])
            {
                max_child_position++;
            }
            // if last_element is bigger than the bigger child node, then we find the right position
            if(last_element > heap_[max_child_position])
            {
                break;
            }
            // else exchange child node and parent node
            heap_[empty_position] = heap_[max_child_position];
            empty_position = max_child_position;
            max_child_position = max_child_position * 2;
        }
        heap_[empty_position] = last_element;  // insert last_element into heap
    }
}

template<typename T>
void MaxHeap<T>::Output()
{
    if(current_size_ == 0)
    {
        cout << "Error: empty max heap.\n";
        return;
    }
    cout << "The heap's contents are :\n";
    for(int index = 1; index <= current_size_; index++)
    {
        cout << heap_[index] << " ";
    }
    cout << endl;
}

void AllOperation()
{
    MaxHeap<int> object;
    cout << "Please some numbers to execute the corresponding operation:\n";
    cout << "0: exit.\n";
    cout << "1: create a MaxHeap.\n";
    cout << "2: insert element into MaxHeap.\n";
    cout << "3: delete max element from MaxHeap.\n";
    cout << "4: print MaxHeap's contents.\n";
    cout << "5: destroy MaxHeap.\n";

    int operate;
    while(cin >> operate)
    {
        switch(operate)
        {
        case 0:
            goto END;
        case 1:
            object.CreateMaxHeap();
            break;
        case 2:
            cout << "Please input your element:\n";
            int element;
            cin >> element;
            object.Insert(element);
            object.Output();
            break;
        case 3:
            object.Delete();
            object.Output();
            break;
        case 4:
            object.Output();
            break;
        case 5:
            object.~MaxHeap();
            cout << "You have destroy the MaxHeap. Please establish MaxHeap before executing operations.\n";
            break;
        default:
            cout << "Input Error! Please input again!\n";
            break;
        }
    }
END:
    ;
}

#endif // MAXHEAP_H_INCLUDED

Test.cc

#include<iostream>
#include"MaxHeap.h"
using namespace std;

int main()
{
    AllOperation();

    return 0;
}

/*
1
6 2
10 14***14 10
2 2***14 10 2
2 20***20 14 2 10
2 15***20 15 2 10 14
2 21***21 15 20 10 14 2
3***20 15 2 10 14
3***15 14 2 10
3***14 10 2
4***14 10 2
5
0
*/

Please indicate the source if you want to reprint: http://blog.csdn.net/gaoxiangnumber1.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值