Go The Way 之 隊列

原創 Go The Way 之 隊列

隊列是一個有序列表,可以用數組或者鏈表來實現
遵循先進先出的遠程,即: 先存入隊列的數據,要先取出,後存入的數據要後取出

簡單隊列(數組實現)

package main

import (
	"errors"
	"fmt"
)
type Queue struct {
	maxSize int
	array [5]int
	front int //表示指向隊列首
	rear int  // 表示指向隊列的尾部

}
func (this *Queue) AddQueue(val int) error {
	// 先判斷隊列是否已經滿了
	if this.rear == this.maxSize - 1 {
		return errors.New("隊列已滿")
	}
	this.rear++

	this.array[this.rear] = val
	return nil
}
// 出隊列
func (this *Queue) GetQueue() (int, error) {
	if this.front == this.rear {
		if this.rear ==  this.maxSize - 1 {
			fmt.Println("開始初始化隊列。。")
			this.rear = -1
			this.front = -1
			return 0, errors.New("隊列已初始化")
		}
		return 0, errors.New("隊列已空")
	}
	this.front++
	val := this.array[this.front]
	return val, nil
}
func (this *Queue) ShowQueue() {

	fmt.Println("隊列當前的情況是:---")
	// this.front 雖然表示隊首,但是不包含隊首的元素
	for i:= this.front+1; i<= this.rear;i++ {
		fmt.Printf("array[%d] = %d\n", i, this.array[i])
	}
}
func main() {

	queue := &Queue{
		maxSize: 5,
		front: -1,
		rear: -1,
	}

	var key string
	var val  int

	for {
		fmt.Println("1. 輸入add 表示添加隊列")
		fmt.Println("2. 輸入get 表示獲取隊列的值")
		fmt.Println("3. 輸入show 表示顯示隊列的值")
		fmt.Println("4. 輸入exit 表示結束程序")
		fmt.Println("請輸入你的操作!\n")

		fmt.Scanln(&key)
		switch key {
			case "add":
				fmt.Println("請輸入你要加入的值:")
				fmt.Scanln(&val)
				err := queue.AddQueue(val)
				if err != nil {
					fmt.Println(err)
				}
			case "get":
				val, err := queue.GetQueue()
				if err != nil {
					fmt.Println(err)
				}
				fmt.Printf("取出的數據爲: %d, 此時隊列還有的數據爲 :\n", val)
				queue.ShowQueue()

			case "show":
				queue.ShowQueue()
			case "exit":
				return
		}

	}
}

循環隊列(數組實現)

package main

import (
	"errors"
	"fmt"
)

/**
環形隊列
 */
type CircleQueue struct {
	maxSize 	int
	array 		[5]int
	head 		int // 指向隊列的隊首
	tail 		int //指向隊列的隊尾
}

func (this *CircleQueue) ISFull () bool {
	//判斷隊列是否已經滿了. 隊列中有一個元素時空的
	return (this.tail + 1) % this.maxSize == this.head
}

// 判斷隊列是否爲空
func (this *CircleQueue) IsEmpty() bool {
	return this.tail == this.head
}

func (this *CircleQueue) Size() int {
	// 尾索引 可能因爲是環形隊列導致小於頭索引
	return ( this.tail + this.maxSize - this.head ) % this.maxSize
}

// 加入隊列
func (this *CircleQueue) Push(val int) error {
	if this.ISFull() {
		return errors.New("隊列已滿")
	}

	this.array[this.tail] = val
	// 環形隊列
	this.tail = (this.tail + 1) % this.maxSize

	return nil
}

//從隊列中取出
func (this *CircleQueue) Pop() (int, error) {
	if this.IsEmpty() {
		return -1, errors.New("隊列已空")
	}

	// 取出數據,head 是指向隊首的,隊首中有值
	val := this.array[this.head]
	// 環形隊列
	this.head = (this.head + 1) % this.maxSize

	return val, nil
}

func (this *CircleQueue) Show() {
	fmt.Println("環形隊列此時數據如下:")
	size := this.Size()
	if size == 0 {
		fmt.Println("隊列已爲空")
	}

	// 設置一個輔助變量
	temHead := this.head

	for i:=0 ;i< size;i++ {
		fmt.Printf("array[%d] = %d \n", temHead, this.array[temHead])
		temHead = (temHead + 1) % this.maxSize
	}
}



func main()  {

	queue := &CircleQueue{
		maxSize: 5,
		tail: 0,
		head: 0,
	}
	// 由於使用數組作爲存儲環形隊列的容器, 爲了實現需要空出最後一個索引代表的位置,作爲隊列的連接處。
	// 所以這裏這個隊列最多存儲 4個值
	var key string
	var val  int

	for {
		fmt.Println("1. 輸入add 表示添加隊列")
		fmt.Println("2. 輸入get 表示獲取隊列的值")
		fmt.Println("3. 輸入show 表示顯示隊列的值")
		fmt.Println("4. 輸入exit 表示結束程序")
		fmt.Println("請輸入你的操作!\n")

		fmt.Scanln(&key)
		switch key {
		case "add":
			fmt.Println("請輸入你要加入的值:")
			fmt.Scanln(&val)
			err := queue.Push(val)
			if err != nil {
				fmt.Println(err)
			}
		case "get":
			val, err := queue.Pop()
			if err != nil {
				fmt.Println(err)
			}
			fmt.Printf("取出的數據爲: %d, 此時隊列還有的數據爲 :\n", val)
			queue.Show()

		case "show":
			queue.Show()
		case "exit":
			return
		}

	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章