数据结构与算法基础-Go语言版-3.队列

目录

前言

一、队列的定义及特点

二、队列的实现1.顺序队列

1.1 队列的顺序结构和循环队列

1.2 循环队列的结构定义

1.3 判断队满与队空

1.4 循环队列的入队

1.5 循环队列的出队

2.链队

2.1 链队的结构定义

2.2 判断队空

2.3 入队

2.4 出队

总结



前言

本文将展示如何使用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不止!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值