資料結構與演算法——二叉堆

readyao發表於2016-01-09

二叉堆(也叫做堆):

本次實現的是最小堆,也就是樹的根結點的值是最小的。如果樹的根結點的值是最大的,那麼該堆是最大堆。
堆是一顆完全二叉樹,一顆樹高為h的完全二叉樹有2^k到2^(k+1)-1個結點,二叉樹的高為log(N)
因為二叉樹非常有規律,我們用陣列來表示二叉樹,在陣列中我們從陣列下標為1處開始儲存。
對於陣列任意位置i上的元素,其左兒子在2*i上,右兒子在(2*i+1)上,它的父親則在i/2上。
在堆中,任意一結點的值小於其子結點的值,所以根據最小堆的性質,最小元素總是會在樹的根結點處找到。

主要的介面:

插入insert

刪除最小元素deleteMin

判斷是否為空isEmpty

二叉堆類:

/*************************************************************************
	> File Name: BinaryHeap.h
	> Author: 
	> Mail: 
	> Created Time: 2016年01月09日 星期六 14時28分57秒
 ************************************************************************/

#ifndef _BINARYHEAP_H
#define _BINARYHEAP_H

#include <vector>
#include <iostream>
using std::vector;
using std::cout;
using std::cin;
using std::endl;

template<class Comparable>
class BinaryHeap{
    public:
        explicit BinaryHeap(int capacity = 100):currentSize(capacity){}
        explicit BinaryHeap(const vector<Comparable> & items);

        bool isEmpty() const;
        const Comparable & findMin() const;
        
        void insert(const Comparable & x);
        void deleteMin();
        void deleteMin(Comparable & minItem);
        void makeEmpty();
        void output();
    private:
        int currentSize;
        vector<Comparable> array;
        
        void buildHeap();
        void percolateDown(int hole);
};


template<class Comparable>
BinaryHeap<Comparable>::BinaryHeap(const vector<Comparable> & items):array(items.size() + 10), currentSize(items.size())
{
    for (int i = 0; i < items.size(); ++i)
        array[i + 1] = items[i];

    buildHeap();
}

template<class Comparable>
void BinaryHeap<Comparable>::buildHeap()
{
    for (int i = currentSize/2; i > 0; i--){
        percolateDown(i);
    }
}

template<class Comparable>
void BinaryHeap<Comparable>::output()
{
    std::cout << "堆:";
    for (int i = 0; i < currentSize; ++i)
        cout << array[i+1] << " ";
    cout << endl;
}

template<class Comparable>
bool BinaryHeap<Comparable>::isEmpty() const
{
    return currentSize == 0;    
}
template<class Comparable>
void BinaryHeap<Comparable>::insert(const Comparable & x)
{
    if(currentSize == array.size()-1)
        array.resize(array.size()*2);
    
    int hole = ++currentSize;

    for (; hole > 1 && x < array[hole/2]; hole /= 2)
        array[hole] = array[hole/2];

    array[hole] = x;
}
/*刪除最小值,也就是刪除堆的根*/
template<class Comparable>
void BinaryHeap<Comparable>::deleteMin()
{
    if(isEmpty()){
        cout << "這是一個空樹。" << endl;
        return;
    }
    
    array[1] = array[currentSize--];
    percolateDown(1);
}

/*刪除最小值,也就是刪除堆的根, 並得到該最小值儲存到minItem中*/
template<class Comparable>
void BinaryHeap<Comparable>::deleteMin(Comparable & minItem)
{
    if(isEmpty()){
        cout << "這是一個空樹。" << endl;
        return;
    }
    minItem = array[1]; 
    array[1] = array[currentSize--];
    percolateDown(1);
}

template<class Comparable>
void BinaryHeap<Comparable>::percolateDown(int hole)
{
    int child;
    Comparable tmp = array[hole];
    for (; hole * 2 <= currentSize; hole = child){
        child = hole * 2;//left child node

        if(child != currentSize && array[child+1] < array[child]){//right child node < left child node
            child++;
        }

        if(array[child] < tmp)//less child node < parent node
            array[hole] = array[child];//將最小的子結點放在父結點的位置
        else
            break;
    }

    array[hole] = tmp;
}


#endif

例項:

/*************************************************************************
	> File Name: use_binary_heap.cpp
	> Author: 
	> Mail: 
	> Created Time: 2016年01月09日 星期六 15時43分24秒
 ************************************************************************/

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

int main()
{
    vector<int> v;
    v.push_back(14);
    v.push_back(16);
    v.push_back(19);
    v.push_back(21);
    v.push_back(19);
    v.push_back(68);
    v.push_back(13);
    v.push_back(65);
    v.push_back(26);
    v.push_back(32);
    v.push_back(31);

    BinaryHeap<int> binHeap(v); 
    binHeap.output();

    vector<int> v2;
    v2.push_back(150);
    v2.push_back(80);
    v2.push_back(40);
    v2.push_back(30);
    v2.push_back(10);
    v2.push_back(70);
    v2.push_back(110);
    v2.push_back(100);
    v2.push_back(20);
    v2.push_back(90);
    v2.push_back(60);
    v2.push_back(50);
    v2.push_back(120);
    v2.push_back(140);
    v2.push_back(130);
    
    BinaryHeap<int> bindHeap2(v2);
    bindHeap2.output();
    cout << "獲得最小元素並刪除最小元素:";
    int minVal;
    bindHeap2.deleteMin(minVal);
    cout << minVal << endl;
    bindHeap2.output();

    return 0;
}





參考:資料結構與演算法分析C++描述(6.3節---二叉樹)

相關文章