6 資料結構 最小堆

2021-10-23 04:37:07 字數 4501 閱讀 3913

開發過程,經常需要對資料集合進行維護。

維護資料結合的資料結構可統稱為容器。

最小堆是維護資料集合的容器的一種,

最小堆具備如下性質:

設v[i]為位置i的元素值

1. 對維護的n個元素,順序儲存於索引為1-n的陣列位置

2. 對索引i,

若索引2*i <= n,有v[i] <= v[2*i],

若索引2*i+1 <= n,有v[i] <= v[2*i+1]。

最小堆為具備特殊性質的容器。

template class minheap

;

minheap()
template minheap::minheap()

minheap(const array::dynarray& arrelements_)
template minheap::minheap(const array::dynarray& arrelements_)

template void minheap::buildheap(const array::dynarray& arrelements_)

for (int _i = _nsize; _i >= 1; _i--) }

template void minheap::adjust(int nindex_)

if (_nr < m_arrelements.getsize()

&& m_arrelements[_nr] < _nmin)

if (_nminpos == nindex_)

else

}

template minheap::minheap(const minheap& mha_)

template typename minheapminheap::operator=(const minheap& mha_)

m_arrelements = mha_.m_arrelements;

return *this;

}

template minheap::~minheap()

template void minheap::add(const t& nt_)

if (_nsize == 0)

// 新元素索引

if ((_nsize + 1) % 2 == 0)

else

// 將新增位置元素設定為指定值

if (nt_ < m_arrelements[_nsize + 1])

else if (nt_ > m_arrelements[_nsize + 1])

else }

template void minheap::smaller(int npos_)

int _np = npos_ / 2;

if (m_arrelements[_np] <= m_arrelements[npos_])

else }

template void minheap::bigger(int npos_)

if (_nr < m_arrelements.getsize()

&& m_arrelements[_nr] < _nmin)

if (_nminpos == npos_)

else

}

template void minheap::delete(int nindex_)

if (_nsize == 1)

m_arrelements[nindex_] = m_arrelements[1] - 1;// 變得比最小還小

smaller(nindex_);// 調節後,原nindex位置元素必位於索引為1位置

m_arrelements[1] = m_arrelements[_nsize];

m_arrelements.deletebyindex(_nsize);

bigger(1);

}

template int minheap::find(std::functionfun_)

} return -1;

}

輸入:無序的含n個元素的陣列

演算法目標:

輸入陣列中n個元素以符合最小堆定義的方式儲存於m_arrelements的索引1,...,n處

正確性證明:

演算法主體採用迴圈迭代實現,迭代實現的一般用迴圈不變式證明正確性

for (int _i = _nsize; _i >= 1; _i--)

迴圈不變式:

區間[_i+1, _nsize]內各個元素均滿足,

對區間內任意位置k的元素,有以下位置約束

若2*k位置元素存在,則有v[k] <= v[2*k]

若2*k+1位置元素存在,則有v[k] <= v[2*k+1]

證明:初始時,區間為[_nsize+1, _nsize]為空 區間,迴圈不變式成立

對_i = k的迭代

依據迴圈不變式【本次迴圈迭代前的各個迭代後,迴圈不變式均滿足】

所有_i > k的迭代處理後,迴圈不變式均滿足

只需證明:adjust(nindex_)

在[nindex_+1, nsize]區間內任意元素均滿足 位置約束前提下,

通過調節[nindex_, nsize]區間內元素位置,

可實現[nindex_, nsize]區間內任意元素均滿足 位置約束的效果即可。

如上述證明成立,則,迴圈不變式成立。

證明:adjust(nindex_)具備上述性質

1. 若k位置元素小於其可能存在的左孩子,右孩子元素

無需處理。

此時,結合演算法前提,可知結論成立。

2. 若k位置元素 比起左孩子,或右孩子大

讓孩子中最小的元素 和 k位置元素交換位置

交換後,對k位置,滿足位置約束

對換入k位置元素的位置t, 該位置的元素相比原來變大了

此時我們希望求解

在[t+1, nsize]區間內任意元素均滿足 位置約束前提下,

通過調節[t, nsize]區間內元素位置,

可實現[t, nsize]區間內任意元素均滿足 位置約束的效果即可。

這和要求解元素問題屬於同類問題。

綜合,在adjust處理中,

我們要麼立即求解。要麼轉化為對同類問題的求解。

我們可以證明,演算法在轉化為同類求解的時候,總是朝著更易終止的方向進行,且可以證明,至多在經歷θ(lg(n))次,遞迴後,必然可以得到立即求解的情形。

綜合,演算法成立。

按新增元素相比預先填充元素大小,實際演變為證明

smaller,bigger

演算法前提/背景:

本來區間[1, nsize]內所有位置均滿足位置約束

現在npos位置元素變小了,導致此位置可能不滿足位置約束

演算法目標:

通過對[1, nsize]各個元素進行位置調整,

使區間[1, nsize]內所有位置均滿足位置約束

1. 若npos_ == 1,無需處理

2. 若 m_arrelements[_np] <= m_arrelements[npos_],無需處理

3. m_arrelements[_np] > m_arrelements[npos_],

交換_np和npos_位置內容。

此時要求解問題:

本來區間[1, nsize]內所有位置均滿足位置約束

現在_np位置元素變小了,導致此位置可能不滿足位置約束

希望通過對[1, nsize]各個元素進行位置調整,使區間[1, nsize]內所有位置均滿足位置約束

這是和原問題同型別的問題

綜合,在smaller處理中,我們要麼立即求解。要麼轉化為對同類問題的求解。

我們可以證明,演算法在轉化為同類求解的時候,總是朝著更易終止的方向進行,且可以證明,至多在經歷θ(lg(n))次,遞迴後,必然可以得到立即求解的情形。

minheap::bigger
類似minheap::smaller
假設元素集合中元素個數為n
minheap()
時間複雜度θ(1)
minheap(const array::dynarray& arrelements_)
時間複雜度θ(nlg(n))
時間複雜度θ(n)
時間複雜度θ(n)
時間複雜度θ(1)
時間複雜度o(lg(n))
時間複雜度o(lg(n))
時間複雜度o(n)

基本資料結構 最小堆

最小堆,是完全二叉樹,其基本定義是任何乙個節點小於其左右子樹的節點 常見操作 加入乙個值,取最小值,刪除最小值 加入乙個值,直接加入到末尾a size 然後該元素上浮到合適位置 最大值即根節點 a 0 刪除最小值,讓末尾元素填充到a 0 然後該元素下沉到合適位置 下沉過程中,選取左右子節點的最小值,...

資料結構 大小堆

如果有乙個關鍵碼的集合k 把它的所有元素按完全二叉樹 的順序儲存方式儲存在乙個一維陣列中,並滿足 ki k2 i 1 且 ki k2 i 2 ki k2 i 1 且 ki k2 i 2 i 0,1,2 則稱這個堆為最小堆 或最大堆 最大堆和最小堆是二叉堆的兩種形式。最大堆 根結點的鍵值是所有堆結點鍵...

資料結構 最小堆的類模板實現

堆資料結構是一種陣列物件,它可以被視為一科完全二叉樹結構。它的特點是父節點的值大於 小於 兩個子節點的值 分別稱為最大堆和最小堆 它常用於管理演算法執行過程中的資訊,應用場景包括堆排序,優先佇列等。1 根結點若有子樹,則子樹一定也是堆。2 根結點一定大於 或小於 子結點。因為要求堆必須是完全二叉樹,...