Golang稀疏数组和队列

稀疏数组(sparsearray)

稀疏数组介绍

当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组。

稀疏数组的处理方法

  1. 记录数组一共有几行几列,有多少个不同的值
  2. 把具有不同值的元素的行列及值记录在一个小规模的数组中,从而缩小程序的规模

案例

image-20220211114614122

package main

import "fmt"

type ValNode struct {
   row int
   col int
   val int
}

func main() {

   //1. 先创建一个原始数组

   var chessMap [11][11]int
   chessMap[1][2] = 1 //黑子
   chessMap[2][3] = 2 //蓝子

   // 2. 输出原始的数组
   for _, v := range chessMap {
      for _, v2 := range v {
         fmt.Printf("%d\t", v2)
      }
      fmt.Println()
   }

   //3. 转成稀疏数组
   //思路:
   //(1)遍历chessMap,如果我们发现有一个元素的值不为0,创建士个node结构体
   //(2).将其放入到对应的切片即可

   var sparseArr []ValNode

   //标准的一个稀疏数组应该还有一个记录元素的二维数组的规模(行和列,默认值)

   valNode := ValNode{
      row: 11,
      col: 11,
      val: 0,
   }

   sparseArr = append(sparseArr, valNode)

   for i, v := range chessMap {
      for j, v2 := range v {
         if v2 != 0 {
            //创建一个ValNode 值结点
            valNode := ValNode{
               row: i,
               col: j,
               val: v2,
            }
            sparseArr = append(sparseArr, valNode)
         }

      }
   }

   //输出稀疏数组
   for i, valNode := range sparseArr {
      fmt.Printf("%d: %d %d %d\n", i, valNode.row, valNode.col, valNode.val)
   }

   //将稀疏数组,存盘 d:/chessmap.data

   //恢复原始数据

   //1.打开这个d:/chessmap.data =>恢复原始数组.

   //2. 这里使用稀疏数组恢复

   //先创建一个原始数据
   var chessMap2 [11][11]int

   //遍历
   for i, valNode := range sparseArr {
      if i != 0 {
         chessMap2[valNode.row][valNode.col] = valNode.val
      }

   }

   for _, v := range chessMap2 {
      for _, v2 := range v {
         fmt.Printf("%d\t", v2)
      }
      fmt.Println()
   }

}

队列

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

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

数组模拟队列

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

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

image-20220211124425653 image-20220211124526674
package main

import (
   "errors"
   "fmt"
   "os"
)

//使用一个结构体管理队列
type Queue struct {
   array   [5]int
   front   int
   rear    int
   maxSize int
}

func (this *Queue) AddQueue(val int) (err error) {
   //先判断队列是否已满
   if this.rear == this.maxSize-1 {
      return errors.New("queue full")
   }

   this.rear++
   this.array[this.rear] = val
   return

}

func (this *Queue) GetQueue() (val int, err error) {
   if this.rear == this.front {
      return -1, errors.New("queue empty")
   }
   this.front++
   val = this.array[this.front]
   return val, err
}

func (this *Queue) ShowQueue() {
   for i := this.front + 1; i <= this.rear; i++ {
      fmt.Printf("arrary[%d] = %d\t", i, this.array[i])
   }
   fmt.Println()
}

func main() {
   queue := &Queue{
      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("加入队列成功")
         } 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. (tail + 1) %maxSize == head [满]
  2. tail == head [空]
  3. 初始化时,tail = 0 head=0
  4. 怎么统计该队列有多少个元素(tail + maxSize - head) % maxSize
package main

import (
   "errors"
   "fmt"
   "os"
)

//使用一个结构体管理环形队列
type CircleQueue struct {
   maxSize int
   array   [5]int
   head    int
   tail    int
}

func (this *CircleQueue) Push(val int) (err error) {
   if this.IsFull() {
      return errors.New("queue 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 0, errors.New("queue empty")
   }
   val = this.array[this.head]
   this.head = (this.head + 1) % this.maxSize
   return
}

func (this *CircleQueue) ListQueue() {
   //取出当前队列有多少元素
   size := this.Size()
   if size == 0 {
      fmt.Println("队列为空")
   }
   tempHead := this.head

   for i := 0; i < size; i++ {
      fmt.Printf("arr[%d] = %d \t", tempHead, this.array[tempHead])
      tempHead = (tempHead + 1) % this.maxSize
   }
}

func (this *CircleQueue) IsFull() bool {
   return (this.tail+1)%this.maxSize == this.head
}

func (this *CircleQueue) IsEmpty() bool {
   return this.tail == this.head
}

func (this *CircleQueue) Size() int {
   return (this.tail + this.maxSize - this.head) % this.maxSize
}

func main() {

   queue := 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 := queue.Push(val)
         if err == nil {
            fmt.Println("加入队列成功")
         } else {
            fmt.Println(err.Error())
         }
      case "get":
         val, err := queue.Pop()
         if err != nil {
            fmt.Println(err.Error())
         } else {
            fmt.Println("取出了这个数", val)
         }
      case "show":
         queue.ListQueue()
      case "exit":
         os.Exit(0)

      }
   }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值