1. 程式人生 > >[Golang] struct配合slice實現迴圈佇列

[Golang] struct配合slice實現迴圈佇列

迴圈佇列

  • 特徵
      使用的頭尾索引永遠都在底層陣列長度下標範圍內,如佇列長度為10,那麼底層陣列長度為11,index範圍[0,10]
  • 解決的問題
      用非迴圈陣列實現的佇列在底層陣列滿的時候有資料搬移的操作,會影響入隊操作;迴圈陣列可以解決這個問題!
  • 與同樣用陣列實現的普通佇列的區別
       1. 迴圈佇列需要專門佔用陣列的一個位置來作為尾結點標識,這個位置不能填充真實資料,所以實際使用的陣列長度會加一。
       2. 迴圈佇列需要一個初始化方法,使用一個預設字元將底層陣列初始化。
       3. 迴圈佇列在滿佇列時,在底層沒有資料搬移操作,入隊 T(n)=O(1)。
  • Code
package main

import (
	"fmt"
	"strconv"
)

type LoopQueue struct {
	Items 	[]string //利用陣列實現佇列
	Head 	uint16	 //頭索引,恆為0
	Tail	uint16	 //尾索引
	Len 	uint16   //限定佇列長度
}


//佇列初始化,將[底層陣列]初始化
func (this *LoopQueue) Init() {
	this.Len = this.Len + 1 //因為最後一個位置不能使用,所以len要比宣告的大一
	for i:=0;i<int(this.Len)
;i++ { this.Items = append(this.Items, "") } } //入列 func (this *LoopQueue) Enqueue(v interface{}){ if ((this.Tail+1) % this.Len) == this.Head { fmt.Println("the queue is full!") return } this.Items[this.Tail] = v.(string) fmt.Printf("%s enqueued, now length: tail:%s \n",v, this.Tail) this.
Tail = (this.Tail+1) % this.Len } //出列 func (this *LoopQueue) Dequeue()interface{}{ if this.Head == this.Tail { fmt.Println("the queue is empty!") return nil } ret := this.Items[this.Head] fmt.Printf("Dequeue: %s! the surplus len: head:%s \n", ret, this.Head) this.Head = (this.Head+1) % this.Len return ret } func main(){ Q := &LoopQueue{Len:10} //設定佇列長度 Q.Init() //初始化佇列 for i:=0;i<12;i++ { //12>10 會提示full s := strconv.Itoa(i) Q.Enqueue(s+s+s) //入列(但只能入10個) } for i:=0;i<3;i++ { Q.Dequeue() //出列3個 } for i:=0;i<12;i++ { //12>10 會提示full s := strconv.Itoa(i) Q.Enqueue(s+s+s) //入列12個(但只能入3個) } for i:=0;i<12;i++ { Q.Dequeue() //出列12次(但只能出10個) } }

使用這種方式有個問題是,使用佇列前需要呼叫一個初始化方法,且初始化方法時用一個預設字元將底層陣列填滿,實在不是一個好的辦法。讀者如有更好的想法,還請指教。