队列的基础知识
队列的基本概念
(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语言版》(严蔚敏、李冬梅、吴伟民著)