golang實現的簡單優先隊列


下面是golang實現的簡單優先隊列,參考信息可以查看https://golang.org/pkg/container/heap/或者https://golang.google.cn/pkg/container/heap/,后面這個網址也是官方提供的網址,關於這個網頁的說明,可以參考https://blog.golang.org/hello-china。

package queue

import "container/heap"

// QItem 表示存儲到這個隊列中需要實現的接口
type QItem interface {
	Less(item QItem) bool
}

// priorityQueueImpl 用於優先隊列底層實現
type priorityQueueImpl []QItem

// Len 獲取隊列長度
func (pqi priorityQueueImpl) Len() int {
	return len(pqi)
}

// Less 用來進行元素比較
func (pqi priorityQueueImpl) Less(i, j int) bool {
	return pqi[i].Less(pqi[j])
}

// Swap 進行交換
func (pqi priorityQueueImpl) Swap(i, j int) {
	pqi[i], pqi[j] = pqi[j], pqi[i]
}

// Push 用來將一個對象壓入隊列中
func (pqi *priorityQueueImpl) Push(x interface{}) {
	item := x.(QItem)
	*pqi = append(*pqi, item)
}

// Pop 將一個對象彈出隊列
func (pqi *priorityQueueImpl) Pop() interface{} {
	old := *pqi
	n := len(old)
	item := old[n-1]
	*pqi = old[0 : n-1]
	return item
}

// PriorityQueue 實現優先隊列
type PriorityQueue struct {
	priorityQueueImpl
}

// NewPriorityQueue 用來構建PriorityQueue
func NewPriorityQueue() *PriorityQueue {
	var pq PriorityQueue
	heap.Init(&pq.priorityQueueImpl)
	return &pq
}

// Push 用來將一個對象壓入到隊列中
func (pq *PriorityQueue) Push(item QItem) {
	heap.Push(&pq.priorityQueueImpl, item)
}

// Pop 用來從隊列中彈出一個對象
func (pq *PriorityQueue) Pop() QItem {
	return heap.Pop(&pq.priorityQueueImpl).(QItem)
}

// Front 用來獲取當前隊列中的最小值
func (pq *PriorityQueue) Front() QItem {
	// 隊列中第一位應該就是最小值
	return pq.priorityQueueImpl[0]
}

// Length 用來獲取當前隊列的長度
func (pq *PriorityQueue) Length() int {
	return pq.priorityQueueImpl.Len()
}

 如果希望一個結構可以存儲到PriorityQueue中,需要實現QItem接口中的函數,即Less函數。下面給出一個簡單的示例:

type Int int

func (i Int) Less(j QItem) bool {
	return i < j.(Int)
}

 注意func (i Int) Less(j QItem) bool中的傳參是QItem,而不是Int,golang當前還不支持泛型,所以,如果想要實現C++的STL的那種效果,應該是不可能的,就算使用反射來使得更多的類型得到支持,也勢必會帶來很大的性能開銷,這個是我不太樂見的。關於將Int類型作為參數進行使用,可以參考下面的測試代碼,這個測試代碼不太規范,不過測試效果應該可以實現:

func Test_NewPriorityQueue(t *testing.T) {
	pq := NewPriorityQueue()
	pq.Push(Int(5))
	pq.Push(Int(8))
	pq.Push(Int(3))

	first := pq.Front()
	if first != Int(3) {
		t.Error("first should be 3")
		return
	}

	first = pq.Pop()
	if first != Int(3) {
		t.Error("first should be 3")
		return
	}

	second := pq.Pop()
	if second != Int(5) {
		t.Error("second should be 5")
		return
	}

	pq.Push(Int(1))
	length := pq.Length()
	if length != 2 {
		t.Error("length should be 2")
		return
	}

	third := pq.Front()
	if third != Int(1) {
		t.Error("third should be 1")
		return
	}

	third = pq.Pop()
	if third != Int(1) {
		t.Error("third should be 1")
		return
	}

	fourth := pq.Pop()
	if fourth != Int(8) {
		t.Error("fourth should be 8")
		return
	}

	length = pq.Length()
	if length != 0 {
		t.Error("empty length should be 0")
		return
	}
}

 在實際使用中,可能需要對func (pq *PriorityQueue) Pop() QItem函數和func (pq *PriorityQueue) Front() QItem函數獲得的值進行類型強轉,使用起來更像是面向對象程序設計的那種方式了。對於需要動態修改優先隊列中成員值的情況,可以參考實現。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM