下面先介紹下什麼是隊列:
(1)隊列是一個有序列表,可以用數組或是鏈表來實現。
(2)遵循先入先出的原則,即:先存入隊列的數據,要先取出,後存入的要後取出。
這裏用Go 實現一個一次性的隊列
package main
import (
"errors"
"fmt"
)
type Query struct {
maxSize int //最大容量
array [4]int //數組
head int //隊首指針
tail int //隊尾指針
}
//初始化一個Query,注意這裏head和tail都爲-1
func NewQueue()*Query {
return &Query{
maxSize: 4,
head: -1,
tail: -1,
}
}
//這裏注意push時隊尾tail向後移動一位
func (q *Query)Push(val int) error{
if q.tail == q.maxSize-1{
return errors.New("隊列已滿")
}
q.tail ++
q.array[q.tail] = val
fmt.Printf("隊首指針爲:%d ---隊尾指針爲:%d ---隊列數組爲:%v\n",q.head,q.tail,q.array)
return nil
}
//這裏注意pop時隊首head向後移動一位
func (q *Query)Pop()(val int ,err error){
if q.head == q.tail{
return 0,errors.New("隊列爲空")
}
q.head ++
val = q.array[q.head]
fmt.Printf("隊首指針爲:%d ---隊尾指針爲:%d ---隊列數組爲:%v\n",q.head,q.tail,q.array)
return
}
func main() {
query := NewQueue()
query.Push(1) //隊首指針爲:-1 ---隊尾指針爲:0 ---隊列數組爲:[1 0 0 0] 因爲push時隊尾指針向後移動一位,所以隊尾指針由-1變爲0
query.Push(2)//隊首指針爲:-1 ---隊尾指針爲:1 ---隊列數組爲:[1 2 0 0]
v,_:=query.Pop()//隊首指針爲:0 ---隊尾指針爲:1 ---隊列數組爲:[1 2 0 0] 因爲pop是隊首指針向後移動一位,所以隊首指針由-1變爲0
fmt.Println(v) // 1
query.Push(3) //隊首指針爲:0 ---隊尾指針爲:2 ---隊列數組爲:[1 2 3 0]
query.Push(4) //隊首指針爲:0 ---隊尾指針爲:3 ---隊列數組爲:[1 2 3 4]
v1,_:=query.Pop()//隊首指針爲:1 ---隊尾指針爲:3 ---隊列數組爲:[1 2 3 4]
fmt.Println(v1)//2
v2,_:=query.Pop()//隊首指針爲:2 ---隊尾指針爲:3 ---隊列數組爲:[1 2 3 4]
fmt.Println(v2)//3
v3,_:=query.Pop()// 隊首指針爲:3 ---隊尾指針爲:3 ---隊列數組爲:[1 2 3 4] 注意這時隊首指針與隊尾指針都爲maxsize -1 時,此時數組無法在用,
fmt.Println(v3) //4
}
下面是打印結果
GOROOT=C:\Go #gosetup
GOPATH=E:\gopath #gosetup
C:\Go\bin\go.exe build -o C:\Users\v_licguo\AppData\Local\Temp\___go_build_dataStructure__1_.exe E:\gopath\src\dataStructure\隊列.go #gosetup
C:\Users\v_licguo\AppData\Local\Temp\___go_build_dataStructure__1_.exe #gosetup
隊首指針爲:-1 ---隊尾指針爲:0 ---隊列數組爲:[1 0 0 0]
隊首指針爲:-1 ---隊尾指針爲:1 ---隊列數組爲:[1 2 0 0]
隊首指針爲:0 ---隊尾指針爲:1 ---隊列數組爲:[1 2 0 0]
1
隊首指針爲:0 ---隊尾指針爲:2 ---隊列數組爲:[1 2 3 0]
隊首指針爲:0 ---隊尾指針爲:3 ---隊列數組爲:[1 2 3 4]
隊首指針爲:1 ---隊尾指針爲:3 ---隊列數組爲:[1 2 3 4]
2
隊首指針爲:2 ---隊尾指針爲:3 ---隊列數組爲:[1 2 3 4]
3
隊首指針爲:3 ---隊尾指針爲:3 ---隊列數組爲:[1 2 3 4]
4
上面這種寫法有一個弊端,就是這個隊列只能使用一次,當隊首指針和隊尾指針同時爲maxSize-1時,這個隊列就不能用了,下面是改進的環形隊列
package main
import (
"errors"
"fmt"
)
type cycleQueue struct {
maxSize int
array [4]int
tail int
head int
}
func newCycleQueue()*cycleQueue {
return &cycleQueue{
maxSize: 4, //這裏實際只能存放三個元素
tail: 0,
head: 0,
}
}
func (c *cycleQueue)Push(val int) error{
if c.tail + 1 == c.maxSize{
fmt.Println("隊列已滿")
return errors.New("隊列已滿")
}
c.array[c.tail] =val
c.tail = (c.tail+1) % c.maxSize
fmt.Printf("隊首指針爲:%d ---隊尾指針爲:%d ---隊列數組爲:%v\n",c.head,c.tail,c.array)
return nil
}
func (c *cycleQueue)Pop()(val int,err error){
if c.head == c.tail{
fmt.Println("隊列爲空")
return -1,errors.New("隊列爲空")
}
val = c.array[c.head]
c.head = (c.head + 1) % c.maxSize
fmt.Printf("隊首指針爲:%d ---隊尾指針爲:%d ---隊列數組爲:%v\n",c.head,c.tail,c.array)
return
}
func (c *cycleQueue)Show() {
for i:=c.head;i<=c.tail-1;i++{
fmt.Printf("%d\t",c.array[i])
}
fmt.Println()
}
func main(){
cyc := newCycleQueue()
cyc.Push(1) //隊首指針爲:0 ---隊尾指針爲:1 ---隊列數組爲:[1 0 0 0]
cyc.Show()//1
cyc.Push(2)//隊首指針爲:0 ---隊尾指針爲:2 ---隊列數組爲:[1 2 0 0]
cyc.Show()//1 2
cyc.Push(3)//隊首指針爲:0 ---隊尾指針爲:2 ---隊列數組爲:[1 2 0 0]
cyc.Show()//1 2 3
cyc.Push(4)//隊列已滿
cyc.Show()//1 2 3
v,_:= cyc.Pop()//隊首指針爲:1 ---隊尾指針爲:3 ---隊列數組爲:[1 2 3 0]
fmt.Println(v)//1
cyc.Show()//2 3
v2,_:= cyc.Pop()//隊首指針爲:2 ---隊尾指針爲:3 ---隊列數組爲:[1 2 3 0]
fmt.Println(v2)//2
cyc.Show()//3
}
下面是運行結果
GOROOT=C:\Go #gosetup
GOPATH=E:\gopath #gosetup
C:\Go\bin\go.exe build -o C:\Users\v_licguo\AppData\Local\Temp\___go_build_dataStructure__3_.exe E:/gopath/src/dataStructure/環形隊列.go #gosetup
C:\Users\v_licguo\AppData\Local\Temp\___go_build_dataStructure__3_.exe #gosetup
隊首指針爲:0 ---隊尾指針爲:1 ---隊列數組爲:[1 0 0 0]
1
隊首指針爲:0 ---隊尾指針爲:2 ---隊列數組爲:[1 2 0 0]
1 2
隊首指針爲:0 ---隊尾指針爲:3 ---隊列數組爲:[1 2 3 0]
1 2 3
隊列已滿
1 2 3
隊首指針爲:1 ---隊尾指針爲:3 ---隊列數組爲:[1 2 3 0]
1
2 3
隊首指針爲:2 ---隊尾指針爲:3 ---隊列數組爲:[1 2 3 0]
2
3
這種環形隊列最大的弊端就是要有一個空的元素始終沒有被用到,即實際只能存儲maxSize -1個元素,下面是環形隊列的改進版,是博主自己根據上面兩種隊列分析出來的,如有疑問歡迎留言,如有錯誤歡迎指出
package main
import (
"errors"
"fmt"
)
type cycleQueue2 struct {
maxSize int
array [4]int
tail int
head int
}
func newCycleQueue2()*cycleQueue2 {
return &cycleQueue2{
maxSize: 4,
tail: -1,
head: -1,
}
}
func (c *cycleQueue2)Push(val int) error{
if c.maxSize ==c.tail - c.head || (c.tail == c.head && c.tail != -1){
fmt.Println("隊列已滿")
return errors.New("隊列已滿")
}
c.tail = (c.tail+1) % c.maxSize
c.array[c.tail] =val
fmt.Printf("隊首指針爲:%d ---隊尾指針爲:%d ---隊列數組爲:%v\n",c.head,c.tail,c.array)
return nil
}
func (c *cycleQueue2)Pop()(val int,err error){
if c.head == c.tail && c.tail == -1{
fmt.Println("隊列爲空")
return -1,errors.New("隊列爲空")
}
c.head =( c.head + 1)%c.maxSize
val = c.array[c.head]
c.array[c.head] = 0
if c.head == c.tail {
c.head ,c.tail= -1,-1
}
fmt.Printf("隊首指針爲:%d ---隊尾指針爲:%d ---隊列數組爲:%v\n",c.head,c.tail,c.array)
return
}
func (c *cycleQueue2)Show() {
if c.head == c.tail && c.tail == -1{
fmt.Println("隊列爲空")
return
}
if c.maxSize ==c.tail - c.head || (c.tail == c.head && c.tail != -1){
fmt.Println("隊列已滿")
return
}
if c.head == c.tail {
}else{
for i:=c.head+1;i<=c.head+c.maxSize;i++{
if c.array[i%c.maxSize] == 0{
break
}
fmt.Printf("%d\t",c.array[i%c.maxSize])
}
}
fmt.Println()
}
func main(){
cyc := newCycleQueue2()
cyc.Push(1)//隊首指針爲:-1 ---隊尾指針爲:0 ---隊列數組爲:[1 0 0 0]
cyc.Show()//1
cyc.Push(2)//隊首指針爲:-1 ---隊尾指針爲:1 ---隊列數組爲:[1 2 0 0]
cyc.Show()//1 2
cyc.Push(3)//隊首指針爲:-1 ---隊尾指針爲:2 ---隊列數組爲:[1 2 3 0]
cyc.Show()//1 2 3
cyc.Push(4)//隊首指針爲:-1 ---隊尾指針爲:3 ---隊列數組爲:[1 2 3 4]
cyc.Show()//1 2 3 4
cyc.Push(4)//隊列已滿
cyc.Show()//1 2 3 4
v,_:= cyc.Pop()//隊首指針爲:0 ---隊尾指針爲:3 ---隊列數組爲:[0 2 3 4]
fmt.Println(v)//1
cyc.Show()//2 3 4
v2,_:= cyc.Pop()//隊首指針爲:1 ---隊尾指針爲:3 ---隊列數組爲:[0 0 3 4]
fmt.Println(v2)//2
cyc.Show()//3 4
v3,_:= cyc.Pop()//隊首指針爲:2 ---隊尾指針爲:3 ---隊列數組爲:[0 0 0 4]
fmt.Println(v3)//3
cyc.Show()//4
v4,_:= cyc.Pop()//隊首指針爲:-1 ---隊尾指針爲:-1 ---隊列數組爲:[0 0 0 0]
fmt.Println(v4)//4
cyc.Show()//
v5,_:= cyc.Pop()//隊列爲空
fmt.Println(v5)//-1
cyc.Show()//
}
下面是運行結果
GOROOT=C:\Go #gosetup
GOPATH=E:\gopath #gosetup
C:\Go\bin\go.exe build -o C:\Users\v_licguo\AppData\Local\Temp\___go_build_dataStructure__2_.exe E:/gopath/src/dataStructure/隊列二.go #gosetup
C:\Users\v_licguo\AppData\Local\Temp\___go_build_dataStructure__2_.exe #gosetup
隊首指針爲:-1 ---隊尾指針爲:0 ---隊列數組爲:[1 0 0 0]
1
隊首指針爲:-1 ---隊尾指針爲:1 ---隊列數組爲:[1 2 0 0]
1 2
隊首指針爲:-1 ---隊尾指針爲:2 ---隊列數組爲:[1 2 3 0]
1 2 3
隊首指針爲:-1 ---隊尾指針爲:3 ---隊列數組爲:[1 2 3 4]
1 2 3 4
隊列已滿
1 2 3 4
隊首指針爲:0 ---隊尾指針爲:3 ---隊列數組爲:[0 2 3 4]
1
2 3 4
隊首指針爲:1 ---隊尾指針爲:3 ---隊列數組爲:[0 0 3 4]
2
3 4
隊首指針爲:2 ---隊尾指針爲:3 ---隊列數組爲:[0 0 0 4]
3
4
隊首指針爲:-1 ---隊尾指針爲:-1 ---隊列數組爲:[0 0 0 0]
4
隊列爲空
-1