• Go队列


    1. 队列的应用场景

    2. 队列的介绍

    1)队列是一个有序列表,可以用数组或是链表来实现。

    2)遵循先入先出的原则。即:先存入队列的数据,要先取出。后存入的要后取出。

    示意图:(使用数组模拟队列示意图)

    3.数组模拟队列

    1)队列本身是有序列表,若使用数组的结构来存储队列的数据,则队列数组声明如下,其中maxSize是该队列的最大容量

    2)因为队列的输出、输入是分别从前后端来处理的,因此需要两个遍历front及rear分别记录队列前后端的下标,front会随着数据输出而改变,而rear则是随着数据输入而改变。

    3)先完成一个非环形的队列(数组来实现)

    当我们将数据存入队列时,称为“addqueue”,addqueue的处理需要有两个步骤:

    (1)将尾指针往后移:rear + 1,front == rear 【空】

    (2)若尾指针rear小于等于队列的最大下标MaxSize-1,则将数据存入rear所指的数组元素中,否则无法存入数据。rear == MaxSize - 1【队列满】

    思路分析:

    单向队列的实现,代码如下:

    package main
    import (
    	"fmt"
    	"errors"
    	"os"
    )
    // 数组模拟队列
    // 使用数组实现队列的思路
    // 1. 创建一个数组array,是作为队列的一个字段
    // 2. front初始化为-1
    // 3. real表示队列尾部,初始化为-1
    // 4. 完成队列的基本查找
    // AddQueue  // 加入数据到队列
    // GetQueue // 从队列取出数据
    // showQueue // 显示队列
    type Queue struct {
    	maxSize int
    	array [5]int // 数组 => 模拟队列
    	front int // 表示指向队列首
    	rear int // 表示指向队列的尾部
    }
    // 1. 添加数据到队列
    func (this *Queue) AddQueue(val int) (err error) {
    	// 先判断队列是否已满
    	if this.rear == this.maxSize - 1 { // 重要的提示:0..........................此时rear是队列尾部,包含最后这个元素
    		return errors.New("queue full")
    	}
    	this.rear++ // 将rear后移一位
    	this.array[this.rear] = val
    	return 
    }
    // 2. 显示队列,找到队首,然后到遍历到队尾
    func (this *Queue) ShowQueue() {
    	fmt.Println("队列当前的情况是:")
    	// this.front 不包含这个队首的元素
    	for i := this.front + 1; i <= this.rear; i++ {
    		fmt.Printf("array[%d]=%d \t", i,this.array[i])
    	}
     
    }
    // 3. 从队列中取出数据
    func (this *Queue) GetQueue() (val int,err error) {
    	// 先判断队列是否为空
    	if (*this).front == (*this).rear { // 队空
    		return -1,errors.New("queue empty")
    	}
    	this.front++
    	val = this.array[this.front]
    	return val, err
    }
    func main() {
    	// 先创建一个队列
    	queue := &Queue{   // 这种形式的写法,下面要调用GetQueue就不能再写成(&queue).GetQueue()
    		maxSize: 5,
    		front: -1,
    		rear: -1,
    	}
    	// 菜单
    	var key string
    	var val int
    	for {
    		fmt.Println("1. 输入add  表示添加数据到队列")
    		fmt.Println("2. 输入get  表示从队列中获取数据")
    		fmt.Println("3. 输入show 表示显示队列")
    		fmt.Println("4. 输入exit 表示显示队列")
    		fmt.Scanln(&key)
    		switch key {
    			case "add":
    				fmt.Println("输入你要入队列数")
    				fmt.Scanln(&val)
    				err := queue.AddQueue(val)
    				if err == nil {
    					fmt.Println("加入队列ok")
    				} else {
    					fmt.Println(err.Error())
    				}
    			case "get":
    				val, err := queue.GetQueue()
    				if err != nil {
    					fmt.Println(err.Error())
    				} else {
    					fmt.Println("从队列中取出了一个数=",val)
    				}
    			case "show":
    				queue.ShowQueue()
    			case "exit":
    				os.Exit(0)
    		}
    	}
    }
    

    对上面代码的小结和说明:

    1)上面代码实现了基本队列结构,但是没有有效的利用数组空间

    2)请思考,如何使用数组,实现一个环形队列

    数组模拟环形队列

    对前面的数组模拟队列的优化,充分利用数组。因此将数组看作是一个环形的。(通过取模的方式来实现即可)

    提醒:

    1)尾索引的下一个为头索引时表示队列满,即将队列容量空出一个作为约定,这个在做判断队列满的时候需要注意(tail + 1) % maxSize == head 【满】

    2)tail == head 【空】

    3)分析思路如下:

    (1)什么时候表示队列满(tail + 1)% maxSize == head

    (2)tail == head 表示空

    (3)初始化时,tail == 0,head == 0

    (4)怎么统计该队列有多少个元素(tail + maxSize - head)% maxSize

    package main
    import (
    	"fmt"
    	"errors"
    	"os"
    )
     
    // 使用一个结构体管理队列
    type CircleQueue struct {
    	maxSize int
    	array [5]int // 数组 => 模拟队列
    	head int // 指向队首
    	tail int // 指向队尾
    }
    // 0. 添加数据到环形队列
    func (this *CircleQueue) Push(val int) (err error) {
    	if this.IsFull() {
    		return errors.New("CirleQueue full")
    	}
    	this.array[this.tail] = val // 把值给尾部
    	this.tail = (this.tail + 1) % this.maxSize
    	return
    }
    func (this *CircleQueue) Pop() (val int, err error) {
    	if this.IsEmpty() {
    		return -1,errors.New("CircleQueue empty")
    	}
    	// 取出
    	val = this.array[this.head]
    	this.head++
    	return val, nil
    }
    // 2. 判断环形队列是否满了
    func (this *CircleQueue) IsFull()bool {
    	return (this.tail + 1) % this.maxSize == this.head
    }
    // 3. 判断环形队列是否为空
    func (this *CircleQueue) IsEmpty() bool {
    	return this.tail == this.head
    }
    // 4. 取出环形队列有多少个元素
    func (this *CircleQueue) Size() int {
    	return (this.tail + this.maxSize - this.head) % this.maxSize
    }
     
    // 5. 显示环形队列
    func (this *CircleQueue) Show() {
    	// 取出当前队列有多少个元素
    	size := this.Size()
    	if size == 0 {
    		fmt.Println("队列为空")
    	}
    	// 设计一个辅助的变量,指向head
    	tempHead := this.head
    	for i := 0; i < size; i++ {
    		fmt.Printf("arr[%d]=%d\t",tempHead,this.array[tempHead])
    		tempHead = (tempHead + 1) % this.maxSize
    	}
    	fmt.Println()
    }
     
    func main() {
    	var circleQueue = &CircleQueue{
    		maxSize: 5,
    		head: 0,
    		tail: 0,
    	}
    	var key string
    	var val int
    	for {
    		fmt.Println("1. 输入add  表示添加数据到环形队列")
    		fmt.Println("2. 输入get  表示从环形队列中获取数据")
    		fmt.Println("3. 输入show 表示显示环形队列")
    		fmt.Println("4. 输入exit 表示退出操作环形队列")
    		fmt.Scanln(&key)
    		switch key {
    			case "add":
    				fmt.Println("输入添加到队列的数据:")
    				fmt.Scanln(&val)
    				err := circleQueue.Push(val)
    				if err != nil {
    					fmt.Println(err.Error())
    				} else {
    					fmt.Println("加入队列 ok")
    				}
    			case "get":
    				val, err := circleQueue.Pop()
    				if err != nil {
    					fmt.Println(err.Error())
    				} else {
    					fmt.Println("从队列中取出了一个数=",val)
    				}
    			case "show":
    				circleQueue.Show()
    			case "exit":
    				os.Exit(0)
    		}
    	}
    }
    

      

  • 相关阅读:
    面试笔试
    scala(9) Monad
    scala (8) 模糊匹配
    scala (7) Set and Tuple
    scala (6) Map
    scala (5) 可变序列和不可变序列
    scala (4) 可变数组和不可变数组
    scala (3) Function 和 Method
    scala (2) while 和变量
    scala (1) for 循环
  • 原文地址:https://www.cnblogs.com/wuchangblog/p/16705030.html
Copyright © 2020-2023  润新知