小根ヒープ(ヒープ)詳細な実装

はじめにヒープ

ヒープは、次の機能を有するデータ構造であります:

1)完全二分木
ヒープに格納されている2)の値が半順序であります

最小ヒープ:値子ノードの親ノードの値は以下であります

最大ヒープ:子ノードの親ノードの値値は以上であります

図1

ヒープメモリ

一般的に、親ノードの配列添字スタックを表すために使用される、私は、(i-1)/ 2上のノードです。それぞれその添字2の左と右の子ノード* I + 1と2 * I + 2、。左と右の子ノード0ノード添字それぞれ1及び2。

図2

スタックは、アレイ内の0から、次の標準のカウントに格納されているので、したがって、スタックがノードIに標識されている設定します。

(1)I = 0、iは、ルートノードなし親ノードであれば、そうでない場合、iはノードをノードにノードの親(I-1)/ 2。

(2)もし2I + 1> N-1、次いでない左の子ノードI、そうでない場合、左の子ノードiは2I + 1のノードに、

(3)2I + 2> N-1、iは右の子ノードでない場合、そうでない場合、右の子ノードiが2I + 2ノードに。

操作をスタック:挿入要素は細根をスタック

新しい要素は、ヒープの最後に追加され、その後、スタック内の秩序を回復するためにツリーを更新:要素を挿入します。
あなたは、アレイ上に新しいデータを挿入するたびに、最終的なものです。これは、新しいデータの親からルートノードに発見され、必ずしも順序付けられたシーケンスで、タスクは現在、注文データに新しいデータを挿入することである-これはに直接データに並べ替えに似ています注文した間隔に組み込ま。私たちは、インターネットの親ノード、スワップからキーと比較し、必要があります。

図3

ヒープアクション:小さなルート最小の要素の山を削除します

定義では、0のすべての山は、データを削除します。スタックの再構成を容易にするために、動作は次にからルートノードから下方修正の開始、ルートノードに割り当てられた最後のデータの実際の値は、スタック-1の要素の数です。さらにこの最小小さな子ノードよりも親ノードが親ノードに対し、調整し、次いでバック考えノードのそれをスイッチングしていない示している場合、左右の子ノードの最初の調整は、最小値を検索します。データ処理を「シンク」するには、ルートから等価。

図4

ヒープ:ヒープを作成します。

完全なバイナリツリーの性質に応じてリーフノード、調整のないようにするため、ため、リーフノード1より大きいため、iは= N / 2 -1、nは開始から移行内部ノードの数。最後はリーフノードのノード開始からです。

ヒープソート

昇順にデータが構築された山を作成する場合は、最初の0の後にヒープは、データの最大ヒープです。これは-1、配列の最後の要素には、要素の現在の数を、データを抽出し、その後、スタックの除去を行います。このようにデータ0のスタックが一つだけのデータヒープ配列要素が順序付けされるまで、上記の手順を繰り返し、最大ヒープデータです。

小根ヒープ実装

#include <iostream>
using namespace std;

const int DefaultSize = 50;

template<typename T>
class MinHeap
{
public:
    //构造函数:建立空堆
    MinHeap(int sz=DefaultSize)
    {
        maxHeapSize = (DefaultSize < sz) ? sz : DefaultSize;
        heap = new T[maxHeapSize];
        currentSize = 0;
    }

    //构造函数通过一个数组建立堆
    MinHeap(T arr[],int n)
    {
        maxHeapSize = (DefaultSize < n) ? n : DefaultSize;
        heap = new T[maxHeapSize];
        for(int i=0;i<n;i++)
        {
            heap[i] = arr[i];
        }
        currentSize = n;
        int currentPos = (currentSize - 2) / 2; //找最初调整位置:最后分支结点
        while (currentPos>=0)   //自底向上逐步扩大形成堆
        {
            siftDowm(currentPos, currentSize - 1);  //局部自上向下下滑调整
            currentPos--;   //再向前换一个分支结点
        }
    }

    //将x插入到最小堆中
    bool Insert(const T& x)
    {
        if(currentSize==maxHeapSize)
        {
            cout << "Heap Full!" << endl;
            return false;
        }
        heap[currentSize] = x;  //插入
        siftUp(currentSize);    //向上调整
        currentSize++;  //堆计数+1
        return true;
    }

    bool RemoveMin(T& x)
    {
        if(!currentSize)
        {
            cout << "Heap Empty!" << endl;
            return false;
        }
        x = heap[0];    //返回最小元素
        heap[0] = heap[currentSize - 1];    //最后元素填补到根结点
        currentSize--;
        siftDowm(0, currentSize - 1);   //自上向下调整为堆
        return true;
    }

    void output()
    {
        for(int i=0;i<currentSize;i++)
        {
            cout << heap[i] << " ";
        }
        cout << endl;
    }

protected:

    //最小堆的下滑调整算法
    void siftDowm(int start, int end)   //从start到end下滑调整成为最小堆
    {
        int cur = start;
        int min_child = 2 * cur + 1;    //先记max_child是cur的左子女位置
        T temp = heap[cur];
        while (min_child <=end)
        {
            if (min_child<end&&heap[min_child]>heap[min_child + 1]) //找到左右孩子中最小的一个
                min_child++;

            if(temp<=heap[min_child])
                break;
            else
            {
                heap[cur] = heap[min_child];
                cur = min_child;
                min_child = 2 * min_child + 1;
            }
        }
        heap[cur] = temp;
    }

    //最小堆的上滑调整算法
    void siftUp(int start)  //从start到0上滑调整成为最小堆
    {
        int cur = start;
        int parent = (cur - 1) / 2;
        T temp = heap[cur];
        while (cur>0)
        {
            if(heap[parent]<=temp)
                break;
            else
            {
                heap[cur] = heap[parent];
                cur = parent;
                parent = (parent - 1) / 2;
            }
        }
        heap[cur] = temp;   //回放temp中暂存的元素
    }
private:    //存放最小堆中元素的数组
    T* heap;
    int currentSize;    //最小堆中当前元素个数
    int maxHeapSize;    //最小堆最多允许元素个数
};

//------------------------主函数-------------------------
int main(int argc, char* argv[])
{
    MinHeap<int> h;
    h.Insert(8);
    h.Insert(5);
    h.Insert(7);
    h.Insert(9);
    h.Insert(6);
    h.Insert(12);
    h.Insert(15);
    h.output();

    int out;
    cout << static_cast<int> (h.RemoveMin(out)) << endl;
    h.output();

    int arr[10] = { 15,19,13,12,18,14,10,17,20,11 };
    MinHeap<int> h1(arr,10);
    h1.output();
}

おすすめ

転載: www.cnblogs.com/WindSun/p/11444446.html