数据结构之Go实现队列


队列的基础知识


队列的基本概念

(1)队列的定义

队列简称队,是一种操作受限的线性表,其限制为仅允许在表的一端进行插入,在表的另一端进行删除。可进行插入的一端称为队尾( Rear ),可进行删除的一端称为队头( Front )。

向队列中插入新的元素称为进队,新元素进队后就成为新的队尾元素;从队列中删除元素称为出队,元素出队后,其后继元素就成为新的队头元素。

(2)队列的特征

队列的特点是先进先出( FIFO )。

(3) 队列的存储结构

队列按存储结构可分为顺序队和链队两种,可用顺序表和链表来存储队列。


队列的结构体定义

(1)顺序队列

// Array
type SeqQueue struct {
		Data [MaxSize]interface{}
		Length int
}

type SeqQueue struct{
		Data []interface{}
		Front int
		Rear int
}

// Slice
type SliceQueue struct {
		Data []interface{}
		Length int
}

(2)链表队列

type LinkedQueueNode struct {
		Value interface{}
		Next *LinkedQueueNode
}

type LinkedQueueNode struct {
		Front *LinkedQueueNode
		Rear *LinkedQueueNode
}

队列的实现


数组队列

(1)数组队列的基本操作如下代码所示。

type Operate interface {
		// 初始化队列
        InitSeqQueue()
        // 判断队列是否为空
        IsEmpty() bool
        // 获取队列的长度
        Len() int
        // 输出队列
        DisplayQueue()
        // 获取对首元素
        GetFrontElem() interface{}
        // 获取对尾元素
        GetRearElem() interface{}
        // 元素进队
        EnterQueue(v interface{})
        // 元素出队
        RemoveQueue() interface{}
}

(2)在任意目录下创建一个项目,在该项目下创建一个名为 seqqueue.go 的程序编写实现以上的功能,该程序的具体代码如下所示。

package SeqQueue

import (
        "errors"
        "fmt"
)

const MaxSize = 20

type SeqQueue struct {
        Data   [MaxSize]interface{}
        Length int
}

func NewSeqQueue() *SeqQueue {
        return new(SeqQueue)
}

type Operate interface {
        InitSeqQueue()
        IsEmpty() bool
        Len() int
        DisplayQueue()
        GetFrontElem() interface{}
        GetRearElem() interface{}
        EnterQueue(v interface{})
        RemoveQueue() interface{}
}

func (q *SeqQueue) InitSeqQueue() {
        q.Length = 0
}

func (q *SeqQueue) IsEmpty() bool {
        return q.Length == 0
}

func (q *SeqQueue) Len() int {
        return q.Length
}

func (q *SeqQueue) DisplayQueue() {
        if q.IsEmpty() {
                fmt.Println("The SeqQueue is empty!")
        } else {
                fmt.Printf("队列中的元素为: ")
                for i := 0; i < q.Length; i++ {
                        fmt.Printf("%d ", q.Data[i])
                }
                fmt.Println()
        }
}

func (q *SeqQueue) GetFrontElem() interface{} {
        if q.IsEmpty() {
                panic(errors.New("The SeqQueue is empty!\n"))
        }
        return q.Data[0]
}

func (q *SeqQueue) GetRearElem() interface{} {
        if q.IsEmpty() {
                panic(errors.New("The SeqQueue is empty!\n"))
        }
        return q.Data[q.Length-1]
}

func (q *SeqQueue) EnterQueue(v interface{}) {
        if q.Length > MaxSize {
                panic(errors.New("The SeqQueue is full!\n"))
        } else {
                q.Data[q.Length] = v
                q.Length++
                fmt.Printf("Elem %d is entered into the SeqQueue!\n", v)
        }
}

func (q *SeqQueue) RemoveQueue() interface{} {
        if q.IsEmpty() {
                panic(errors.New("The SeqQueue is empty!\n"))
        } else {
                v := q.Data[0]
                for i := 1; i < q.Length; i++ {
                        q.Data[i-1] = q.Data[i]
                }
                q.Length--
                fmt.Printf("Elem %d is removed from the SeqQueue!\n", v)
                return v
        }
}

(3)在该项目的目录下创建一个名为 seqqueue_test.go 的程序测试以上的功能逻辑是否正确,该程序的具体代码如下所示。

package SeqQueue

import (
        "fmt"
        "testing"
)

func TestNewSeqQueue(t *testing.T) {
        var q Operate
        q = NewSeqQueue()
        q.InitSeqQueue()
        q.DislpayQueue()
        q.EnterQueue(12)
        q.EnterQueue(24)
        q.EnterQueue(33)
        q.DisplayQueue()
        fmt.Printf("THe SeqQueue front elem is %d\n", q.GetFrontElem())
        fmt.Printf("The SeqQueue rear elem is %d\n", q.GetRearElem())
        fmt.Printf("The SeqQueue's length is %d\n", q.Len())
        q.EnterQueue(22)
        q.RemoveQueue()
        q.EnterQueue(55)
        q.DisplayQueue()
}

(4)在项目的目录下执行 go test 命令进行测试验证,程序运行的结果如下所示。

The SeqQueue is empty!
Elem 12 is entered into the SeqQueue!
Elem 24 is entered into the SeqQueue!
Elem 33 is entered into the SeqQueue!
队列中的元素为: 12 24 33 
THe SeqQueue front elem is 12
The SeqQueue rear elem is 33
The SeqQueue's length is 3
Elem 22 is entered into the SeqQueue!
Elem 12 is removed from the SeqQueue!
Elem 55 is entered into the SeqQueue!
队列中的元素为: 24 33 22 55 

切片队列

  • 不带头结点

(1)切片队列的基本操作如下代码所示。

type Operate interface {
		// 初始化队列
        InitSliceQueue()
        // 判断队列是否为空
        IsEmpty() bool
        // 获取队列的长度
        Len() int
        // 输出队列
        DisplayQueue()
        // 获取对首元素
        GetFrontElem() interface{}
        // 获取对尾元素
        GetRearElem() interface{}
        // 元素进队
        EnterQueue(v interface{})
        // 元素出队
        RemoveQueue() interface{}
}

(2)在任意目录下创建一个项目,在该项目下创建一个名为 slicequeue.go 的程序编写实现以上的功能,该程序的具体代码如下所示。

package SliceQueue

import (
        "errors"
        "fmt"
)

type SliceQueue struct {
        Data   []interface{}
        Length int
}

func NewSliceQueue() *SliceQueue {
        q := &SliceQueue{}
        q.Data = make([]interface{}, 0)
        q.Length = 0
        return q
}

type Operate interface {
        InitSliceQueue()
        IsEmpty() bool
        Len() int
        DisplayQueue()
        GetFrontElem() interface{}
        GetRearElem() interface{}
        EnterQueue(v interface{})
        RemoveQueue() interface{}
}

func (q *SliceQueue) InitSliceQueue() {
        q.Length = 0
}

func (q *SliceQueue) IsEmpty() bool {
        return q.Length == 0
}

func (q *SliceQueue) Len() int {
        return q.Length
}

func (q *SliceQueue) GetFrontElem() interface{} {
        if q.IsEmpty() {
                panic(errors.New("The SliceQueue is empty!\n"))
        } else {
                return q.Data[0]
        }
}

func (q *SliceQueue) GetRearElem() interface{} {
        if q.IsEmpty() {
                panic(errors.New("The SliceQueue is empty!\n"))
        } else {
                return q.Data[q.Length-1]
        }
}

func (q *SliceQueue) DisplayQueue() {
        if q.IsEmpty() {
                fmt.Println("The SliceQueue is empty!")
        } else {
                fmt.Printf("队列中的元素为: ")
                i := 0
                for i < q.Length {
                        fmt.Printf("%d ", q.Data[i])
                        i++
                }
                fmt.Println()
        }
}

func (q *SliceQueue) EnterQueue(v interface{}) {
        q.Data = append(q.Data, v)
        q.Length++
        fmt.Printf("Elem %d is entered into the SliceQueue!\n", v)
}

func (q *SliceQueue) RemoveQueue() interface{} {
        if q.IsEmpty() {
                panic(errors.New("The SliceQueue is empty!\n"))
        } else {
                v := q.Data[0]
                q.Data = q.Data[1:]
                q.Length--
                fmt.Printf("Elem %d is removed from the SliceQueue!\n", v)
                return v
        }
}

(3)在该项目的目录下创建一个名为 slicequeue_test.go 的程序测试以上的功能逻辑是否正确,该程序的具体代码如下所示。

package SliceQueue

import (
        "fmt"
        "testing"
)

func TestNewSliceQueue(t *testing.T) {
        var q Operate
        q = NewSliceQueue()
        q.InitSliceQueue()
        q.DisplayQueue()
        q.EnterQueue(4)
        q.EnterQueue(2)
        q.EnterQueue(6)
        q.DisplayQueue()
        fmt.Printf("The SliceQueue's length is %d\n", q.Len())
        q.EnterQueue(1)
        q.RemoveQueue()
        q.EnterQueue(7)
        q.DisplayQueue()
        fmt.Printf("The SliceQueue front elem is %d\n", q.GetFrontElem())
        fmt.Printf("The SliceQueue rear elem is %d\n", q.GetRearElem())

}

(4)在项目的目录下执行 go test 命令进行测试验证,程序运行的结果如下所示。

The SliceQueue is empty!
Elem 4 is entered into the SliceQueue!
Elem 2 is entered into the SliceQueue!
Elem 6 is entered into the SliceQueue!
队中的元素为: 4 2 6 
The SliceQueue's length is 3
Elem 1 is entered into the SliceQueue!
Elem 4 is removed from the SliceQueue!
Elem 7 is entered into the SliceQueue!
队中的元素为: 2 6 1 7 
The SliceQueue front elem is 2
The SliceQueue rear elem is 7

  • 带头结点

(1)切片队列的基本操作如下代码所示。

type Operate interface {
		// 初始化队列
        InitSliceQueue()
        // 判断队列是否为空
        IsEmpty() bool
        // 获取队列的长度
        Len() int
        // 输出队列
        DisplayQueue()
        // 获取对首元素
        GetFrontElem() interface{}
        // 获取对尾元素
        GetRearElem() interface{}
        // 元素进队
        EnterQueue(v interface{})
        // 元素出队
        RemoveQueue() (v interface{})
}

(2)在任意目录下创建一个项目,在该项目下创建一个名为 slicequeue.go 的程序编写实现以上的功能,该程序的具体代码如下所示。

package SliceQueue

import (
        "errors"
        "fmt"
)

type SliceQueue struct {
        Data  []interface{}
        Front int
        Rear  int
}

func NewSliceQueue() *SliceQueue {
        return &SliceQueue{Data: make([]interface{}, 0)}
}

type Operate interface {
        InitSliceQueue()
        IsEmpty() bool
        Len() int
        DisplayQueue()
        GetFrontElem() interface{}
        GetRearElem() interface{}
        EnterQueue(v interface{})
        RemoveQueue() (v interface{})
}

func (q *SliceQueue) InitSliceQueue() {
        q.Front = 0
        q.Rear = q.Front
}

func (q *SliceQueue) IsEmpty() bool {
        return q.Front == q.Rear
}

func (q *SliceQueue) Len() int {
        return q.Rear - q.Front
}

func (q *SliceQueue) GetFrontElem() interface{} {
        if q.IsEmpty() {
                panic(errors.New("The SliceQueue is empty!\n"))
        } else {
                return q.Data[q.Front]
        }
}

func (q *SliceQueue) GetRearElem() interface{} {
        if q.IsEmpty() {
                panic(errors.New("The SliceQueue is empty!\n"))
        } else {
                return q.Data[q.Rear-1]
        }
}

func (q *SliceQueue) DisplayQueue() {
        if q.IsEmpty() {
                fmt.Println("The SliceQueue is empty!")
        } else {
                fmt.Printf("队中的元素为: ")
                i := 0
                for i < q.Len() {
                        fmt.Printf("%d ", q.Data[i])
                        i++
                }
                fmt.Println()
        }
}

func (q *SliceQueue) EnterQueue(v interface{}) {
        q.Data = append(q.Data, v)
        q.Rear++
        fmt.Printf("Elem %d is entered into the SliceQueue!\n", v)
}

func (q *SliceQueue) RemoveQueue() (v interface{}) {
        if q.IsEmpty() {
                panic(errors.New("The SliceQueue is empty!\n"))
        } else {
                v, q.Data = q.Data[0], q.Data[1:]
                q.Rear--
                fmt.Printf("Elem %d is removed from the SliceQueue!\n", v)
                return v
        }
}

(3)在该项目的目录下创建一个名为 slicequeue_test.go 的程序测试以上的功能逻辑是否正确,该程序的具体代码如下所示。

package SliceQueue

import (
        "fmt"
        "testing"
)

func TestNewSliceQueue(t *testing.T) {
        var q Operate
        q = NewSliceQueue()
        q.InitSliceQueue()
        q.DisplayQueue()
        q.EnterQueue(4)
        q.EnterQueue(2)
        q.EnterQueue(6)
        q.DisplayQueue()
        fmt.Printf("The SliceQueue's length is %d\n", q.Len())
        q.EnterQueue(1)
        q.RemoveQueue()
        q.EnterQueue(7)
        q.DisplayQueue()
        fmt.Printf("The SliceQueue front elem is %d\n", q.GetFrontElem())
        fmt.Printf("The SliceQueue rear elem is %d\n", q.GetRearElem())
}

(4)在项目的目录下执行 go test 命令进行测试验证,程序运行的结果如下所示。

The SliceQueue is empty!
Elem 4 is entered into the SliceQueue!
Elem 2 is entered into the SliceQueue!
Elem 6 is entered into the SliceQueue!
队中的元素为: 4 2 6 
The SliceQueue's length is 3
Elem 1 is entered into the SliceQueue!
Elem 4 is removed from the SliceQueue!
Elem 7 is entered into the SliceQueue!
队中的元素为: 2 6 1 7 
The SliceQueue front elem is 2
The SliceQueue rear elem is 7

循环队列

(1)循环队列的基本操作如下代码所示。

type Operate interface {
		// 初始化循环队列
        InitSeqQueue()
        // 判断循环队列是否为空
        IsEmpty() bool
        // 判断循环队列是否满
        IsFull() bool
        // 获取循环队列的长度
        Len() int
        // 输出循环队列
        DisplayQueue()
        // 获取对首元素
        GetFrontElem() interface{}
        // 获取对尾元素
        GetRearElem() interface{}
        // 元素进队
        EnterQueue(v interface{})
        // 元素出队
        RemoveQueue() interface{}
}

(2)在任意目录下创建一个项目,在该项目下创建一个名为 ringqueue.go 的程序编写实现以上的功能,该程序的具体代码如下所示。

package RingQueue

import (
        "errors"
        "fmt"
)

const MaxSize = 50

type RingQueue struct {
        Data  [MaxSize]interface{}
        Front int
        Rear  int
}

func NewRingQueue() *RingQueue {
        return new(RingQueue)
}

type Operate interface {
        InitRingQueue()
        IsEmpty() bool
        IsFull() bool
        Len() int
        DisplayQueue()
        GetFrontElem() interface{}
        GetRearElem() interface{}
        EnterQueue(v interface{})
        RemoveQueue() interface{}
}

func (q *RingQueue) InitRingQueue() {
        q.Front = 0
        q.Rear = q.Front
}

func (q *RingQueue) IsEmpty() bool {
        return q.Front == q.Rear
}

func (q *RingQueue) IsFull() bool {
        return q.Front == (q.Rear+1)%MaxSize
}

func (q *RingQueue) GetFrontElem() interface{} {
        return q.Data[q.Front+1]
}

func (q *RingQueue) GetRearElem() interface{} {
        return q.Data[q.Rear]
}

func (q *RingQueue) Len() int {
        return q.Rear - q.Front
}

func (q *RingQueue) DisplayQueue() {
        if q.IsEmpty() {
                fmt.Println("The RingQueue is empty!")
        } else {
                fmt.Printf("循环队列的元素为: ")
                p := q.Front
                for p != q.Rear {
                        p = (p + 1) % MaxSize
                        fmt.Printf("%d ", q.Data[p])
                }
                fmt.Println()
        }
}

func (q *RingQueue) EnterQueue(v interface{}) {
        if q.IsFull() {
                panic(errors.New("The RingQueue is full!\n"))
        } else {
                q.Rear = (q.Rear + 1) % MaxSize
                q.Data[q.Rear] = v
                fmt.Printf("Elem %d is entered into the RingQueue!\n", v)
        }
}

func (q *RingQueue) RemoveQueue() interface{} {
        if q.IsEmpty() {
                panic(errors.New("The RingQueue is empty!\n"))
        } else {
                v := q.Data[q.Front+1]
                q.Front = (q.Front + 1) % MaxSize
                fmt.Printf("Elem %d is removed from the RingQueue!\n", v)
                return v
        }
}

(3)在该项目的目录下创建一个名为 ringqueue_test.go 的程序测试以上的功能逻辑是否正确,该程序的具体代码如下所示。

package RingQueue

import (
        "fmt"
        "testing"
)

func TestRingQueue(t *testing.T) {
        var q Operate
        q = NewRingQueue()
        q.InitRingQueue()
        q.DisplayQueue()
        q.EnterQueue(1)
        q.EnterQueue(3)
        q.EnterQueue(5)
        q.DisplayQueue()
        fmt.Printf("The RingQueue front elem is %d\n", q.GetFrontElem())
        fmt.Printf("The RingQueue rear elem is %d\n", q.GetRearElem())
        q.RemoveQueue()
        q.RemoveQueue()
        fmt.Printf("The RingQueue's length is %d\n", q.Len())
        q.DisplayQueue()
}

(4)在项目的目录下执行 go test 命令进行测试验证,程序运行的结果如下所示。

The RingQueue is empty!
Elem 1 is entered into the RingQueue!
Elem 3 is entered into the RingQueue!
Elem 5 is entered into the RingQueue!
循环队列的元素为: 1 3 5 
The RingQueue front elem is 1
The RingQueue rear elem is 5
Elem 1 is removed from the RingQueue!
Elem 3 is removed from the RingQueue!
The RingQueue's length is 1
循环队列的元素为: 5 

链表队列

(1)链表队列的基本操作如下代码所示。

type Operate interface {
		// 初始化链表队列
        InitLinkedQueue()
        // 判断链表队列是否为空
        IsEmpty() bool
        // 获取链表队列的长度
        Len() int
        // 输出链表队列
        DisplayQueue()
        // 获取对首元素
        GetFrontElem() interface{}
        // 获取对尾元素
        GetRearElem() interface{}
        // 元素进队
        EnterQueue(v interface{})
        // 元素出队
        RemoveQueue() interface{}
}

(2)在任意目录下创建一个项目,在该项目下创建一个名为 linkedqueue.go 的程序编写实现以上的功能,该程序的具体代码如下所示。

package LinkedQueue

import (
        "errors"
        "fmt"
)

type LinkedQueueNode struct {
        Value interface{}
        Next  *LinkedQueueNode
}

type LinkedQueue struct {
        Front *LinkedQueueNode
        Rear  *LinkedQueueNode
}

func NewLinkedQueueNode() *LinkedQueueNode {
        return new(LinkedQueueNode)
}

func NewLinkedQueue() *LinkedQueue {
        return new(LinkedQueue)
}

type Operate interface {
        InitLinkedQueue()
        IsEmpty() bool
        Len() int
        DisplayQueue()
        GetFrontElem() interface{}
        GetRearElem() interface{}
        EnterQueue(v interface{})
        RemoveQueue() interface{}
}

func (q *LinkedQueue) InitLinkedQueue() {
        q.Front = nil
        q.Rear = q.Front
}

func (q *LinkedQueue) IsEmpty() bool {
        return q.Rear == nil
}

func (q *LinkedQueue) Len() (i int) {
        i = 0
        head := q.Front
        for head != q.Rear {
                i++
                head = head.Next
        }
        return i + 1
}

func (q *LinkedQueue) DisplayQueue() {
        head := q.Front
        if head == nil {
                fmt.Printf("The LinkedQueue is empty!\n")
        } else {
                fmt.Printf("链表队列中的元素为: ")
                for i := 0; head != q.Rear; i++ {
                        fmt.Printf("%d ", head.Value)
                        head = head.Next
                }
                fmt.Printf("%d\n", q.Rear.Value)
        }
}

func (q *LinkedQueue) GetFrontElem() interface{} {
        if q.Front == nil {
                panic(errors.New("The LinkedQueue is empty!\n"))
        } else {
                return q.Front.Value
        }
}

func (q *LinkedQueue) GetRearElem() interface{} {
        if q.Front == nil || q.Rear == nil {
                panic(errors.New("The LinkedQueue is empty!\n"))
        } else {
                return q.Rear.Value
        }
}

func (q *LinkedQueue) EnterQueue(v interface{}) {
        s := NewLinkedQueueNode()
        s.Value = v
        if q.Front == nil {
                q.Front = s
                q.Rear = s
        } else {
                q.Rear.Next = s
                q.Rear = s
        }
        fmt.Printf("Elem %d is entered into the LinkedQueue!\n", v)

}

func (q *LinkedQueue) RemoveQueue() interface{} {
        if q.Front == nil {
                panic(errors.New("The LinkedQueue is empty!\n"))
        } else {
                v := q.Front.Value
                q.Front = q.Front.Next
                if q.Front == nil {
                        q.Rear = nil
                }
                fmt.Printf("Elem %d is removed from the LinkedQueue!\n", v)
                return v
        }
}

(3)在该项目的目录下创建一个名为 linkedqueue_test.go 的程序测试以上的功能逻辑是否正确,该程序的具体代码如下所示。

package LinkedQueue

import (
        "fmt"
        "testing"
)

func TestNewLinkedQueue(t *testing.T) {
        var q Operate
        q = NewLinkedQueue()
        q.InitLinkedQueue()
        q.DisplayQueue()
        q.EnterQueue(1)
        q.EnterQueue(3)
        q.EnterQueue(5)
        q.DisplayQueue()
        f := q.GetFrontElem()
        fmt.Printf("The LinkedQueue front elem is %d\n", f)
        r := q.GetRearElem()
        fmt.Printf("The LinkedQueue rear elem is %d\n", r)
        q.EnterQueue(4)
        q.EnterQueue(7)
        q.DisplayQueue()
        fmt.Printf("The LinkedQueue rear elem is %d\n", q.GetRearElem())
        q.RemoveQueue()
        fmt.Printf("The LinkedQueue' length is %d\n", q.Len())
        q.DisplayQueue()
}

(4)在项目的目录下执行 go test 命令进行测试验证,程序运行的结果如下所示。

The LinkedQueue is empty!
Elem 1 is entered into the LinkedQueue!
Elem 3 is entered into the LinkedQueue!
Elem 5 is entered into the LinkedQueue!
链表队列中的元素为: 1 3 5
The LinkedQueue front elem is 1
The LinkedQueue rear elem is 5
Elem 4 is entered into the LinkedQueue!
Elem 7 is entered into the LinkedQueue!
链表队列中的元素为: 1 3 5 4 7
The LinkedQueue rear elem is 7
Elem 1 is removed from the LinkedQueue!
The LinkedQueue' length is 4
链表队列中的元素为: 3 5 4 7

  • 参考书籍:《数据结构教程 第6版》(李春葆 主编)

  • 参考书籍:《数据结构 C语言版》(严蔚敏、李冬梅、吴伟民著)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

물の韜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值