算法導(dǎo)論第六章-最小優(yōu)先隊列

首先是最小堆算法的golang實現(xiàn):

package main

// MinHeap 最小堆的結(jié)構(gòu)
type MinHeap struct {
    heapSize int
    heap     []int
}

// LEFT 返回子樹左邊的元素
func (A *MinHeap) LEFT(i int) int {
    return i << 1
}

// RIGHT 返回子樹右邊的元素
func (A *MinHeap) RIGHT(i int) int {
    return (i<<1 + 1)
}

// PARENT 返回父結(jié)點
func (A *MinHeap) PARENT(i int) int {
    return i >> 1
}

// MinHeapify 最小化堆
func (A *MinHeap) MinHeapify(i int) {
    smallest := i
    l := A.LEFT(i + 1)
    r := A.RIGHT(i + 1)
    if l <= A.heapSize && A.heap[l-1] < A.heap[i] {
        smallest = l - 1
    }
    if r <= A.heapSize && A.heap[r-1] < A.heap[smallest] {
        smallest = r - 1
    }
    if smallest != i {
        A.heap[smallest], A.heap[i] = A.heap[i], A.heap[smallest]
        A.MinHeapify(smallest)
    }
}

// BuildMinHeap 構(gòu)建最小堆
func (A *MinHeap) BuildMinHeap() {
    for i := A.heapSize / 2; i >= 0; i-- {
        A.MinHeapify(i)
    }
}

// GetHeapSize 獲得堆大小
func (A *MinHeap) GetHeapSize() int {
    return A.heapSize
}

// AlterHeapSize 更改堆大小
func (A *MinHeap) AlterHeapSize(i int) {
    A.heapSize = i
}

// GetElement 獲得堆中的元素
func (A *MinHeap) GetElement(i int) int {
    return A.heap[i]
}

// SetElement 更新堆中的元素
func (A *MinHeap) SetElement(i int, key int) {
    A.heap[i] = key
}

// Swap 交換堆中的元素
func (A *MinHeap) Swap(i int, j int) {
    A.heap[i], A.heap[j] = A.heap[j], A.heap[i]
}

// Append 向堆中追加元素
func (A *MinHeap) Append(i int) {
    A.heap = append(A.heap, i)
}

// NewMinHeap 最小里堆的構(gòu)造函數(shù)
func NewMinHeap(heapSize int, a []int) *MinHeap {
    minHeap := MinHeap{heapSize: heapSize, heap: a}
    minHeap.BuildMinHeap()
    return &minHeap
}

然后是基于最小堆的最小隊列的golang實現(xiàn):

package main

import (
    "errors"
    "fmt"
)

// MinHeapInterface 最小堆的接口
type MinHeapInterface interface {
    LEFT(i int) int
    RIGHT(i int) int
    PARENT(i int) int
    MinHeapify(i int)
    BuildMinHeap()
    GetHeapSize() int
    AlterHeapSize(int)
    GetElement(i int) int
    Swap(i int, j int)
    SetElement(i int, key int)
    Append(i int)
}

// MinPriorityQueue 最小隊列的接口(只要實現(xiàn)了最小隊列的那些方法就能實現(xiàn)最小隊列)
type MinPriorityQueue interface {
    MinHeapInterface
}

// Insert 把元素key插入到隊列S中
func Insert(S MinPriorityQueue, key int) {
    const MaxInt = int(^uint(0) >> 1)
    S.AlterHeapSize(S.GetHeapSize() + 1)
    S.Append(MaxInt)
    DecreaseKey(S, S.GetHeapSize()-1, key)
}

// Minimum 返回S中具有最小關(guān)鍵字的元素
func Minimum(S MinPriorityQueue) int {
    return S.GetElement(0)
}

// ExtractMin 去掉并返回S中具有最小關(guān)鍵字的元素
func ExtractMin(S MinHeapInterface) (int, error) {
    heapSize := S.GetHeapSize()
    if heapSize < 1 {
        return 0, errors.New("HEAP UNDERFLOW")
    }
    min := S.GetElement(0)
    S.Swap(0, heapSize-1)
    S.AlterHeapSize((heapSize - 1))
    S.MinHeapify(0)
    return min, nil
}

// DecreaseKey 將元素i的關(guān)鍵字減少到key,這里假設(shè)key的值不小于i的原關(guān)鍵字值
func DecreaseKey(S MinHeapInterface, i int, key int) error {
    if key >= S.GetElement(i) {
        return errors.New("new key is bigger than current key")
    }
    S.SetElement(i, key)
    for i > 0 && S.GetElement(S.PARENT(i)) > S.GetElement(i) {
        S.Swap(i, S.PARENT(i))
        i = S.PARENT(i)
    }
    return nil
}

func main() {
    s := []int{15, 13, 9, 5, 12, 8, 7, 4, 0, 6, 2, 1}
    a := NewMinHeap(len(s), s)
    for a.heapSize > 0 {
        i, _ := ExtractMin(a)
        fmt.Println(i)
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市衩辟,隨后出現(xiàn)的幾起案子胞此,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件脯颜,死亡現(xiàn)場離奇詭異悠汽,居然都是意外死亡,警方通過查閱死者的電腦和手機缸棵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進(jìn)店門舟茶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事吧凉∷沓觯” “怎么了?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵阀捅,是天一觀的道長胀瞪。 經(jīng)常有香客問我,道長饲鄙,這世上最難降的妖魔是什么凄诞? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮忍级,結(jié)果婚禮上帆谍,老公的妹妹穿的比我還像新娘。我一直安慰自己轴咱,他們只是感情好汛蝙,可當(dāng)我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著朴肺,像睡著了一般窖剑。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上宇挫,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天苛吱,我揣著相機與錄音,去河邊找鬼器瘪。 笑死翠储,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的橡疼。 我是一名探鬼主播援所,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼欣除!你這毒婦竟也來了住拭?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤历帚,失蹤者是張志新(化名)和其女友劉穎滔岳,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體挽牢,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡谱煤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了禽拔。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片刘离。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡室叉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出硫惕,到底是詐尸還是另有隱情茧痕,我是刑警寧澤,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布恼除,位于F島的核電站踪旷,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏缚柳。R本人自食惡果不足惜埃脏,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一搪锣、第九天 我趴在偏房一處隱蔽的房頂上張望秋忙。 院中可真熱鬧,春花似錦构舟、人聲如沸灰追。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽弹澎。三九已至,卻和暖如春努咐,著一層夾襖步出監(jiān)牢的瞬間苦蒿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工渗稍, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留佩迟,地道東北人。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓竿屹,卻偏偏與公主長得像报强,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子拱燃,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內(nèi)容