Go实现数据结构之队列

队列(Queue)

  • 队列是一个有序列表,可以用数组或链表实现
  • 遵循先入先出原则

数组模拟队列

  • 队列本身是有序数列,若使用数组的结构来存储队列的数据,则队列数组的声明如下 其中maxSize是该队列的最大容量
  • 队列的输入、输出是分别从前后端来处理,因此需要两个变量front及rear分别记录队列前后端的下标,front会随数据输出而改变,而rear则是随数据的输入而改变

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-irWHTpRV-1611058357382)(https://i.loli.net/2021/01/17/RJIKUMdmjDp8uck.png)]

  • addqueue处理步骤:
    • 将尾指针后移:rear+1,front==rear(空)
    • 若尾指针rear小于等于队列的最大下标Maxsize-1,则将数据存入rear所指的数组元素中,否则无法存入数据。rear==Maxsize-1(队满)
package main

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

//使用结构体管理队列

type Queue struct {
	maxSize int
	front   int
	rear    int
	array   []int
}

//队列初始化
func (this *Queue) initQue(n int) {
	this.maxSize = n
	this.array = make([]int, n)
	this.front = -1
	this.rear = -1
	return
}

//添加数据到队列
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
}

//从队列中取出数据,不包含front
func (this *Queue) GetQueue()(val int,err error){
	//判断队列是否为空
	if this.front==this.rear{
		return -1,errors.New("queue empty")
	}
	this.front++
	val = this.array[this.front]
	return val,err
}

//显示队列,找到队首,然后遍历到队尾,不包含队首的元素
func (this *Queue) ShowQueue() {
	fmt.Println("队列当前的情况是:")
	for i := this.front + 1; i <= this.rear; i++ {
		fmt.Printf("array[%d]=%d\t\n", i, this.array[i])
	}
}
func main() {
	var queue Queue
	queue.initQue(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.Scanln(&key)
		switch key {
		case "add":
			fmt.Println("输入你要入队列的数据")
			fmt.Scanln(&val)
			err := queue.AddQueue(val)
			if err != nil {
				fmt.Println(err.Error())
			} else {
				fmt.Println("加入队列ok")
			}
		case "get":
			val,err :=queue.GetQueue()
			if err !=nil{
				fmt.Println(err.Error())
			}else{
				fmt.Println(val)
			}
		case "show":
			queue.ShowQueue()
		case "exit":
			os.Exit(0)
		}
	}
}

缺点及优化:

缺点:分析可得,向队列插入元素至队满后,即使出队列,rear的值仍为栈顶,不能有新元素入栈,造成浪费

优化:环形队列,将数组看成环形的(取模实现)

  • 尾索引的下一个为头索引时为满
  • 尾索引==头索引时为空
//使用结构体管理一个环形队列
type CircleQueue struct {
	maxSize int
	array   [5]int
	head    int //指向队列队首
	tail    int //指向队尾
}

//入队列
func (this *CircleQueue) AddQueue(val int) (err error) {
	if this.IsFull() {
		return errors.New("queue full")
	}
	//this.tail在队列尾部,但不包含最后一个元素
	this.array[this.tail] = val
	this.tail = (this.tail + 1) % this.maxSize
	return
}

func (this *CircleQueue) GetQueue() (val int, err error) {
	if this.IsEmpty() {
		return 0, errors.New("queue Empty")
	}
	//取出,head只想队首,并且含队首元素
	val = this.array[this.head]
	this.head = (this.head + 1) % this.maxSize
	return
}

//显示队列
func (this *CircleQueue) ShowQueue() {
	size := this.Size()
	if size == 0 {
		fmt.Println("队列为空")
	}

	//设计一个辅助变量,指向head
	tempHead := this.head
	for i := 0; i < size; i++ {
		fmt.Printf("array[%d]=%d\t", tempHead, this.array[tempHead])
		tempHead = (tempHead + 1) % this.maxSize
	}
	fmt.Println()
}

//判断环形队列是否满
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 main() {
	queue := &CircleQueue{
		maxSize: 5,
		head:    0,
		tail:    0,
	}
	var key string
	var val int
	for {
		fmt.Println("1.:输入add 表示添加数据到队列")
		fmt.Println("2.:输入get 表示从队列获取数据")
		fmt.Println("3.:输入show 表示显示队列")
		fmt.Println("4.:输入exit 表示退出")

		fmt.Scanln(&key)
		switch key {
		case "add":
			fmt.Println("输入你要入队列的数据")
			fmt.Scanln(&val)
			err := queue.AddQueue(val)
			if err != nil {
				fmt.Println(err.Error())
			} else {
				fmt.Println("加入队列ok")
			}
		case "get":
			val, err := queue.GetQueue()
			if err != nil {
				fmt.Println(err.Error())
			} else {
				fmt.Println(val)
			}
		case "show":
			queue.ShowQueue()
		case "exit":
			os.Exit(0)
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值