Go---稀疏数组、队列

数据结构
 数据结构是一门研究算法的学科,只从有了编程语言也就有了数据结构.学好数据结构可以编写出更加漂亮,更加有效率的代码。
 程序=数据结构+算法

稀疏数组

  当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组。
稀疏数组的处理方法是:
  1) 记录数组一共有几行几列,有多少个不同的值
  2) 把具有不同值的元素的行列及值记录在一个小规模的数组中,从而缩小程序的规模

 应用实例
1)使用稀疏数组,来保留类似前面的二维数组(棋盘、地图等等)

2)把稀疏数组存盘,并且可以从新恢复原来的二维数组数
3)整体思路分析

 

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)

            }

        }

    }

    //输出稀疏数组

    fmt.Println("当前的稀疏数组是::::")

    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

    //遍历sparseArr [遍历文件每一行]

    for i,valNode := range sparseArr {

        if i != 0 { //跳过第一行记录值

            chessMap2[valNode.row][valNode.col] = valNode.val

        }

       

    }

    //输出恢复的chessMap2

    fmt.Println("恢复后的原始数据。。。。。")

    for _,v := range chessMap {

        for _,v2 := range v {

            fmt.Printf("%d\t",v2)

        }

        fmt.Println()

    }

}

队列

队列是一个有序列表,可以用数组或是链表来实现。
遵循先入先出的原则。即:先存入队列的数据,要先取出。后存入的要后取出

数组模拟队列(不是环形)
1.队列本身是有序列表,若使用数组的结构来存储队列的数据,则队列数组的声明如下其中maxSize是该队列的最大容量。
2.因为队列的输出、输入是分别从前后端来处理,因此需要两个变量front及rear分别记录队列前后端的下标,front 会随着数据输出而改变,而rear则是随着数据输入而改变,如图所示:

当我们将数据存入队列时称为”addqueue",addqueue 的处理需要有两个步骤:
1)将尾指针往后移: rear+1 , front == rear【空】
2)若尾指引rear小于等于队列的最大下标 MaxSize-1,则将数据存入 rear所指的数组元素中,否则无法存入数据。rear ==MaxSize-1[队列满]

package main

import (

    "fmt"

    "os"

    "errors"

)

//使用结构体管理队列

type Queue struct {

    maxSize int

    array [5]int //数组--》模拟队列

    front int  //表示指向队列首

    rear int //表示指向队列的尾部

}

//添加数据到队列

func(this *Queue)AddQueue(val int)(err error){

    //先判断队列事是否已满

    if this.rear == this.maxSize -1 {  //重要提示,rear 是队列尾部(含最后的元素)

        return errors.New("queue full")

    }

    this.rear++ //rear后移

    this.array[this.rear]=val

    return

}

//显示队列

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])

      }

    fmt.Println()

}

//从队列中取出数据

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 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(err.Error())

            }else{

                fmt.Println("加入队列ok")

            }

        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)

        default:

            fmt.Println("输入错误,请重新输入")

        }

    }

}

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

注意:

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

2) tail == head表示空
3)初始化时,tail = 0  head= 0
4)怎么统计该队列有多少个元素 (tail + maxSize - head ) % maxSize

package main

import (

    "fmt"

    "os"

    "errors"

)

//使用一个结构体管理环形队列

type CircleQueue struct {

    maxSize int //5

    array [5]int //数组

    head int // 指向队列的头 0

    tail int //指向队列的尾 0

}

//入队列ADDQueue(push) GetQueue(pup)

func (this *CircleQueue) Push(val int)(err error){

    if this.IsFull() {

        return errors.New("queue full")

    }

    //分析出this.tail 在队列尾部,但是包含最后的元素

    this.array[this.tail] = val //把值给尾部

    this.tail=(this.tail+1)%this.maxSize //===tail++

    return

}

//出队列

func (this *CircleQueue) Pop()(val int,err error){

    if this.IsEmpty(){

        return 0,errors.New("queue empty")

    }

    //取出  head 是指向队首,并且包含队首元素

    val = this.array[this.head]

    this.head=(this.head+1)%this.maxSize //===head++

    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

    }

    fmt.Println()

}

//判断环形队列为满

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(err.Error())

            }else{

                fmt.Println("加入队列ok")

            }

        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)

        default:

            fmt.Println("输入错误,请重新输入")

        }

    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值