數據結構之最小堆的實現C++版

 

完全二叉樹之所以用數組的方式存在,在於他的一個特性 若子節點爲i,則父節點爲(i-1)/2,注意c++特性,該結果肯定是個整數。

若父節點爲j,則子節點必爲2*j+1;則在數組裏面可以非常方便的通過下標去獲取。

建堆的核心思想:

  堆在index的值爲heap[index],然後其兩個孩子的值邊可求得,左孩子爲heap[index*2+1],右孩子爲heap[index*2+2]。

首先比較左邊孩子與右邊孩子,獲取較小值的孩子,然後讓heap[index]與值較小的孩子進行比較。若值小則交換值,並且移動index到值較小孩子的位置,否則退出調整。

下面看代碼,有註釋:

#pragma once
template<class T>
class JBMinHeap
{
private:
    //申請堆空間
    T *_minHeap = NULL;
    int _index,_maxSize;
public:
    JBMinHeap(int maxSize) {
        _maxSize = maxSize;
        _minHeap = new T[_maxSize];
        _index = -1;
    }
    JBMinHeap(JBMinHeap &h) {
        _index = h._index;
        _maxSize = h._maxSize;
        _minHeap = new T[_maxSize];
        for (int i = 0;i<_maxSize) {
            *_minHeap[i] = *h._minHeap[i];
        }
    }
    ~JBMinHeap() {
        delete[]_minHeap;
    }
    //獲取整個最小堆的頭部指針
    T * getMinHeap() {
        return _minHeap;
    }
    //判斷堆是不是空的
    bool isEmpty() {
        return _index == -1;
    }
    bool add(T x) {
        if (isFull()) {
            return false;
        }
        _index++;
        _minHeap[_index] = x;
        return true;
    }
    bool isFull() {
        return _index == _maxSize;
    }
    //堆進行向下調整
    void adjustDown(int index);
    //隊進行向上調整
    void adjustUp(int index);
    //建堆運算
    void createMinHeap() {
        if (isEmpty()) {
            return;
        }
        for (int i = (_index-1)/2;i >-1;i--) {//直接從倒數第二層 逐層向下調整
            adjustDown(i);
        }
    }
};
template<class T>
void JBMinHeap<T>::adjustDown(int index) {
    if (isEmpty()) {
        return;
    }
    while (index<_index)
    {
        T temp = _minHeap[index];//將當前索引的位置的值保存下來
        int oneC = 2 * index + 1;//獲取到兩個孩子的位置
        int twoC = 2 * index + 2;
        if (oneC == _index) {//若第一個孩子是整個堆最後一個位置 則直接執行交換操作並結束執行
                _minHeap[index] = _minHeap[oneC];
                _minHeap[oneC] = temp;
                return;
        }
        if (twoC >_index) {//如果第二個孩子的索引位置越界 結束執行
            return;
        }
        if (_minHeap[oneC] <= _minHeap[twoC]) {//正常情況的數據交互執行
            if (temp > _minHeap[oneC]) {
                _minHeap[index] = _minHeap[oneC];
                _minHeap[oneC] = temp;
                index = oneC;
            }
            else {//如果該處索引值已經是比兩個孩子小 則結束循環
                index = _index;
            }
        }
        else 
        {
            if (temp > _minHeap[twoC]) {
                _minHeap[index] = _minHeap[twoC];
                _minHeap[twoC] = temp;
                index = twoC;
            }
            else 
            {
                index = _index;
            }
        }
    }
}
template<class T>
void JBMinHeap<T>::adjustUp(int index) {
    if (index > _index) {//大於堆的最大值直接return
        return;
    }
    while (index>-1)
    {
        T temp = _minHeap[index];
        int father = (index - 1) / 2;
        if (father >= 0) {//若果索引沒有出界就執行想要的操作
            if (temp < _minHeap[father]) {
                _minHeap[index] = _minHeap[father];
                _minHeap[father] = temp;
                index=father;
            }
            else {//若果已經是比父親大 則直接結束循環
                index = -1;
            }
        }
        else//出界就結束循環
        {
            index = -1;
        }
    }
}

主程序:

#include "stdafx.h"
#include"stdlib.h"
#include"JBQueue.h"
#include"JBStack.h"
#include"JBBinaryTree.h"
#include"JBMinHeap.h"

int main()
{
    {
        JBMinHeap<int> jb(10);
        jb.add(20);
        jb.add(18);
        jb.add(19);
        jb.add(13);
        jb.add(42);
        jb.add(5);
        jb.createMinHeap();
        int *p=jb.getMinHeap();
        printf("整理爲最小堆:\n");
        for (int i = 0;i < 6;i++) {
            printf("%d\n",p[i]);
        }
    }
    system("pause");
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章