目录
前言
本文将展示如何使用go语言实现队列的结构以及队列的基本方法:如入队,出队等
一、队列的定义及特点
- 队列的定义:队列是限定删除只能在表头位置,插入只能在表尾位置的特殊线性表。
- 队列的特点:先入先出,后入后出,插入元素只能在队尾,出队只能发生在队头
二、队列的实现
1.顺序队列
1.1 队列的顺序结构和循环队列
- 顺序队列
- 结构
- 缺点
头指针之前的空间无法使用了
- 从上图可以看出来,一般的顺序链,在元素插入队列满了之后,只能进行出队操作,而一旦进行出队操作,之前的队头空间就被废弃了,有点浪费空间,如下图所示。
- 从上图可以看出来,一般的顺序链,在元素插入队列满了之后,只能进行出队操作,而一旦进行出队操作,之前的队头空间就被废弃了,有点浪费空间,如下图所示。
- 结构
- 循环队列
- 循环队列解决了上述缺点,当我们尾指针指向队列容器的尾端时,如果我们仍然想插入元素,可以去队列容器的头部看看是否还有空间,如果有空间就继续插入,如果没有空间则断定队列已满。如图所示
- 循环队列解决了上述缺点,当我们尾指针指向队列容器的尾端时,如果我们仍然想插入元素,可以去队列容器的头部看看是否还有空间,如果有空间就继续插入,如果没有空间则断定队列已满。如图所示
1.2 循环队列的结构定义
type cQueue struct{
front int // 队头
tail int // 队尾
queue []int // 队列容器
length int //队列中元素的长度
size int // 队列的尺寸,既队列中元素的最大个数
}
func newCQueue(size int)*cQueue{
return &cQueue{
front:0,
tail:0,
queue:make([]int,size),
length:0,
size:size,
}
}
1.3 判断队满与队空
// 判断队空
func (cq *cQueue)isValid()bool{
return cq.length==0
}
// 判断队满
func (cq *cQueue)isFull()bool{
return cq.length == cq.size
}
1.4 循环队列的入队
func (cq *cQueue)insertQueue(data int)error{
if cq.isFull(){ // 队满就不允许入队
return errors.New("the queue is full,can not insert any value\n")
}
cq.queue[cq.tail]=data // 在队尾插入数据
cq.tail = (cq.tail+1)%cq.size // 保证是循环队列
cq.length++
return nil
}
1.5 循环队列的出队
func (cq * cQueue)outQueue()(int,error){
if cq.isValid(){ // 队空则无法出队
return -1,errors.New("the queue is empty,no value can out \n")
}
result := cq.queue[cq.front] // 从队头出队
cq.front = (cq.front+1)%cq.size // 保证循环队列
cq.length--
return result,nil
}
2.链队
2.1 链队的结构定义
- 链队的结构如下图所示,其中头指针指向头节点,头节点不存放数据,而尾指针则是随着队尾移动,始终指向队列中最后一个元素。
type lQNode struct{
data int
next *lQNode
}
func newLQNode(data int)*lQNode{
return &lQNode{
data:data,
next:nil,
}
}
type lQueue struct{
front *lQNode // 头指针指向头节点,头节点不存放数据
tail *lQNode // 尾指针始终指向队尾元素
length int
}
func initLQueue()*lQueue{
head :=newLQNode(-1)
return &lQueue{
front:head, //队列中没有元素时,队尾队头都指向头节点
tail:head,
length:0,
}
}
2.2 判断队空
func (lq *lQueue)isValid()bool{
return lq.front == lq.tail
}
2.3 入队
func (lq *lQueue)insertQueue(data int){
temp := newLQNode(data) // 创建一个新节点
lq.tail.next = temp // 插入队尾
lq.tail = temp // 队尾指针指向队列最后一个元素
lq.length++
}
2.4 出队
func (lq *lQueue)outQueue()(int,error){
if lq.isValid(){ // 队空无法出队
return -1,errors.New("the queue is valid,no values can be outed\n")
}
temp := lq.front.next // 找到队头元素
lq.front.next = temp.next // 删除队头元素
temp.next = nil
if temp == lq.tail{ // 注意:如果删除的元素是队尾元素,则必须把队尾指针重置到队头,否则队尾指针就会丢失
lq.tail = lq.front
}
return temp.data,nil
}
总结
以上便是关于数据结构中队列的基本内容,关于队列的应用与练习,会在后续二叉树的层序遍历中继续给出。如有错误或更好的方法欢迎和我讨论。
生命不息,coding不止!