什么是队列
队列,又称为伫列(queue),计算机科学中的一种抽象资料型别,是先进先出(FIFO, First-In-First-Out)的线性表。在具体应用中通常用链表或者数组来实现。队列只允许在后端(称为rear)进行插入操作,在前端(称为front)进行删除操作。
队列的操作方式和堆栈类似,唯一的区别在于队列只允许新数据在后端进行添加[1]。
Golang 实现单链队列(数组)
在 Golang 中使用数组实现一个单链队列,除了需要创建一个数组存储数据外,还要定义最大值(maxSize)、头指针(front)和尾指针(rear),其中头指针和尾指针的初始值为-1。
当向队列中插入数据时,头指针不变,尾指针+1,最后在数组的尾指针位置赋值。
当从队列中取出数据时,尾指针不变,头指针+1,最后在数组的头指针位置取值。
实现代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
| package main
import ( "errors" "fmt" )
type Queue struct { front int rear int maxSize int data [5]int }
func main() { var queue = &Queue{ front: -1, rear: -1, maxSize: 5, }
var selectOption int var inputValue int exit: for { fmt.Print("请选择一种操作:\n") fmt.Print("1. 将数据加入队列。\n") fmt.Print("2. 从队列中取出数据。\n") fmt.Print("3. 显示队列中所有数据。\n") fmt.Print("4. 退出。\n") fmt.Scanln(&selectOption) switch selectOption { case 1: fmt.Print("输入数据:\n") fmt.Scanln(&inputValue) err := queue.EnQueue(inputValue) if err != nil { fmt.Println(err.Error()) } else { fmt.Println(("加入数据成功!\n")) } case 2: val, err := queue.DeQueue() if err != nil { fmt.Println(err.Error()) } else { fmt.Printf("取出队列值为:%d\n", val) } case 3: queue.LtQueue() case 4: break exit } } fmt.Println("退出成功!") }
func (this *Queue) EnQueue(val int) error { if this.rear == this.maxSize-1 { return errors.New("队列已满.") } this.rear++ this.data[this.rear] = val return nil }
func (this *Queue) DeQueue() (int, error) { if this.front == this.rear { return -1, errors.New("队列为空.") } this.front++ return this.data[this.front], nil }
func (this *Queue) LtQueue() { if this.front == this.rear { fmt.Println("队列为空.") }
for i := this.front + 1; i <= this.rear; i++ { fmt.Printf("Queue %d = %d\n", i, this.data[i]) } }
|
Golang 实现循环队列(数组)
在 Golang 中使用数组实现一个循环队列,需要的队列结构同单链队列一样,不过头指针和尾指针的初始值为0。
一个定义了最大元素数n的队列,其存储的实际最大元素数量为n-1。一开始我以为是我实现的方式有问题,后来经过各种方案的尝试后,发现这种结构实现循环队列就是这样。
当向队列中插入数据时,头指针不变,在数组的尾指针位置赋值,最后尾指针 +1 并取余。
当从队列中取出数据时,尾指针不变,在数组的头指针位置取值,最后头指针 +1 并取余。
实现代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
| package main
import ( "errors" "fmt" )
type Queue struct { front int rear int maxSize int data [5]int }
func main() { queue := &Queue{ front: 0, rear: 0, maxSize: 5, } var selectOption int var inputValue int
exit: for { fmt.Print("请选择一种操作:\n") fmt.Print("1. 将数据加入队列。\n") fmt.Print("2. 从队列中取出数据。\n") fmt.Print("3. 显示队列中所有数据。\n") fmt.Print("4. 退出。\n") fmt.Scanln(&selectOption) switch selectOption { case 1: fmt.Print("输入数据:\n") fmt.Scanln(&inputValue) err := queue.EnQueue(inputValue) if err != nil { fmt.Println(err.Error()) } else { fmt.Println(("加入数据成功!")) } case 2: val, err := queue.DeQueue() if err != nil { fmt.Println(err.Error()) } else { fmt.Printf("取出队列值为:%d\n", val) } case 3: err := queue.LtQueue() if err != nil { fmt.Println(err.Error()) } case 4: break exit } } fmt.Println("退出成功!") }
func (this *Queue) EnQueue(val int) error { if (this.rear+1)%this.maxSize == this.front { return errors.New("队列已满") } this.data[this.rear] = val this.rear = (this.rear + 1) % this.maxSize return nil }
func (this *Queue) DeQueue() (val int, error) { if this.front == this.rear { return -1, errors.New("队列为空") } val = this.data[this.front] this.front = (this.front + 1) % this.maxSize return }
func (this *Queue) LtQueue() error { if this.front == this.rear { return errors.New("队列为空") } for i := 0; i < this.Length(); i++ { fmt.Printf("Queue [%d] = %d\n", i, this.data[(this.front+i)%this.maxSize]) } return nil }
func (this *Queue) Length() int { return (this.maxSize - this.front + this.rear) % this.maxSize }
|