go_队列

1、队列(queue)

1.1 队列的应用场景

​ 银行排队叫号

1.2 队列介绍

队列是一个有序列表,可以用数组或链表来实现

遵循先入先出的原则。即:先存入队列的数据要先取出,后存入的要后取出

示意图:(使用数组模拟队列示意图)

1.3 数组模拟队列

1、队列本身是有序列表,若使用数组的结构来存储队列的数据,则队列数组的声明如下,其中maxSize是该队列的最大容量

2、因为队列的输出、输入是分别从前后端处理的,因此需要两个变量front及rear分别记录队列前后端的下标,front会随着数据输入而改变,如下图所示:

3、先完成一个非环形的队列(数组来实现)

思路分析 :

代码实现:

package main

import (
	"errors"
	"fmt"
	"os"
)

//创建一个队列结构体
type queue struct {
	Maxsize int
	array[5] int
	front int //队列首部
	rear int //队列尾部
}

//队列添加元素
func (this *queue) addqueue(val int)(err error){

	//判断队列是否已满
	if this.rear==this.Maxsize-1{
		return errors.New("queue full")
	}
	this.rear++
	this.array[this.rear]=val
	return
}

//展示队列元素
func (this *queue) showqueue() (err error) {
	fmt.Println("队列当前情况:")
	//遍历front到rare的元素
	//front不包含队首的元素
	for i :=this.front+1;i < this.rear;i++{
		fmt.Println("array[%d]=%d\n",i,this.array[i] )
	}
	return
}

//获取队列元素
func (this *queue) getqueue()(val int,err error){
	//判断队列是否为空
	if this.front == this.rear{
		return -1,errors.New("quell emptry")
	}
	this.front++
	val = this.array[this.front]
	return val,err
}

func main(){
	//1、先创建一个队列元素
	queue :=&queue{
		Maxsize :5,
		front :-1, //队列首部
		rear :-1, //队列尾部
	}

	var key string
	var i int
	for {
		//1、add
		fmt.Println("1、输入add,添加队列元素")
		//2、get
		fmt.Println("2、输入get,获取队列元素")
		//3、show
		fmt.Println("3、输入show,遍历队列元素")
		fmt.Println("4、输入exit,遍历队列元素")

		fmt.Scanln(&key)
		switch key {
		case "add":
			fmt.Println("输入add入队列数")
			fmt.Scanln(&i)
			err := queue.addqueue(i)
			if err !=nil{
				fmt.Println("添加数据失败,err:",err.Error())
			}else {
				fmt.Println("加入队列成功")
			}
		case "get":
			fmt.Println("输入get获取队列数")
			val,err := queue.getqueue()
			if err !=nil{
				fmt.Println("获取数据失败,err:",err)
				return
			}else {
				fmt.Println("取出的数据val:=",val)
			}
		case "show":
			fmt.Println("输入show显示队列元素")
			queue.showqueue()
		case "exit":
		os.Exit(0)
		}
	}
}

上面代码总结:

1、上面代码实现了基本的队列结构,但是没有有效地利用数组空间

2、思考,如何有效的利用数组空间

1.4数组模拟环形队列

思路:

1、尾索引的下一个为头索引时,表示队列满,即将队列容量空出一个作为约定,再做判断满的时候需要注意[tail+1]==head 表示队列满了

2、tail == head代表队列为空

3、初始化时,tail=0,head = 0

4、怎么统计该队列有多少个元素(tail + maxsize - head)% maxsize

代码实现:

package main

import (
	"errors"
	"fmt"
	"os"
)

//环形队列
type cirequeue struct {
	maxsize int
	head    int
	tail    int
	arry    [5]int
}

//入队列
func (this *cirequeue) Push(val int) (err error) {
	if this.isFull() {
		return errors.New("queue full")
	}
	//this.tail在队列尾部,但是包含最后的元素
	this.arry[this.tail] = val
	this.tail = (this.tail + 1) % this.maxsize
	return
}

//出队列
func (this *cirequeue) Pop() (val int, err error) {
	if this.isEmpty() {
		return 0, errors.New("queue empty")
	}
	val = this.arry[this.head]
	this.head = (this.head + 1) % this.maxsize
	return
}

//遍历队列
func (this *cirequeue) listQueue() (val int) {

	fmt.Println("环形队列情况如下:")
	//取出当前队列的元素
	size := this.size()
	if size == 0 {
		fmt.Println("队列为空")
	}
	//设计一个辅助变量,指向head
	tmphead := this.head
	for i := this.head; i < size; i++ {
		fmt.Println("arr[%d]=%d\t", tmphead, this.arry[tmphead])
		tmphead = (tmphead + 1) % this.maxsize
	}
	fmt.Println()
	return
}

//判断队列是否已满(队列空出末尾的一个位置用作标志位)
func (this *cirequeue) isFull() bool {
	return (this.tail+1)%this.maxsize == this.head
}

//判断队列是否为空
func (this *cirequeue) isEmpty() bool {
	return this.head == this.tail
}

//取出队列中有多少元素
func (this *cirequeue) size() int {
	//关键算法
	return (this.tail + this.maxsize - this.head) % this.maxsize
}

func main() {
	//初始化结构体
	queue := &cirequeue{
		maxsize: 5,
		head:    0,
		tail:    0,
	}

	var key string
	var i int
	for {
		//1、add
		fmt.Println("1、输入add,添加队列元素")
		//2、get
		fmt.Println("2、输入get,获取队列元素")
		//3、show
		fmt.Println("3、输入show,遍历队列元素")
		fmt.Println("4、输入exit,遍历队列元素")

		fmt.Scanln(&key)
		switch key {
		case "add":
			fmt.Println("输入add入队列数")
			fmt.Scanln(&i)
			err := queue.Push(i)
			if err != nil {
				fmt.Println("添加数据失败,err:", err.Error())
			} else {
				fmt.Println("加入队列成功")
			}
		case "get":
			fmt.Println("输入get获取队列数")
			val, err := queue.Pop()
			if err != nil {
				fmt.Println("获取数据失败,err:", err)
				return
			} else {
				fmt.Println("取出的数据val:=", val)
			}
		case "show":
			fmt.Println("输入show显示队列元素")
			queue.listQueue()
		case "exit":
			os.Exit(0)
		}
	}

}

参考学习网站:https://www.bilibili.com/video/BV114411D768

posted @ 2021-03-05 09:36  天下医者不自医  阅读(106)  评论(0编辑  收藏  举报