• Go的数据结构(感谢韩老师)


    稀疏数组

    1.1 先看一个实际的需求

    编写的五子棋程序中,有存盘退出和续上盘的功能
    在这里插入图片描述
    因为该二维数组的很多值是默认值 0, 因此记录了很多没有意义的数据

    1.2 稀疏数组基本介绍

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

    稀疏数组的处理方法是:

    记录数组一共有几行几列,有多少个不同的值
    思想:把具有不同值的元素的行列及值记录在一个小规模的数组中,从而缩小程序的规模
    使用稀疏数组,来保留类似前面的二维数组(棋盘、地图等等)

    把稀疏数组存盘,并且可以从新恢复原来的二维数组数

    1.3 稀疏数组举例说明

    在这里插入图片描述

    1.4 把数组转换为稀疏数组实现

    思路分析:
    在这里插入图片描述
    代码实现:

    package main
    
    import (
    	"bufio"
    	"fmt"
    	"os"
    )
    
    type ValNode struct {
    	row int
    	col int
    	val int
    }
    
    func main() {
    	filePath := "E:/golang开发学习/sparsearray.data"
    	file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0666)
    	if err != nil {
    		fmt.Printf("open file err=%v\n", err)
    		return
    	}
    	//及时关闭file句柄
    	defer file.Close()
    
    	// 1. 创建一个原始数组
    	var chessMap [11][11]int
    	chessMap[1][2] = 1
    	chessMap[2][3] = 2
    
    	// 2. 输出查看原始数组
    	fmt.Println("原始数组为:")
    	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, v1 := range v {
    			if v1 != 0 {
    				// 创建一个ValNode 值节点
    				ValNode.row = i
    				ValNode.col = j
    				ValNode.val = v1
    				sparseArr = append(sparseArr, ValNode)
    			}
    		}
    	}
    
    	// 4. 输出稀疏数组
    	fmt.Println("当前的稀疏数组是:")
    	writer := bufio.NewWriter(file)
    	for _, ValNode := range sparseArr {
    		var s1 = fmt.Sprintf("%d %d %d\n", ValNode.row, ValNode.col, ValNode.val)
    		writer.WriteString(s1)
    		fmt.Printf("%s", s1)
    	}
    	writer.Flush()
    }
    
    • 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

    运行结果

    [Running] go run "e:\golang开发学习\go_pro\test.go"
    原始数组为:
    0	0	0	0	0	0	0	0	0	0	0	
    0	0	1	0	0	0	0	0	0	0	0	
    0	0	0	2	0	0	0	0	0	0	0	
    0	0	0	0	0	0	0	0	0	0	0	
    0	0	0	0	0	0	0	0	0	0	0	
    0	0	0	0	0	0	0	0	0	0	0	
    0	0	0	0	0	0	0	0	0	0	0	
    0	0	0	0	0	0	0	0	0	0	0	
    0	0	0	0	0	0	0	0	0	0	0	
    0	0	0	0	0	0	0	0	0	0	0	
    0	0	0	0	0	0	0	0	0	0	0	
    当前的稀疏数组是:
    11 11 0
    1 2 1
    2 3 2
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    1.5 把稀疏数组还原为原数组

    坑点一:读取后是字符串需要,分割成字符串数组,这里通过Split但是数组最后一个多一个换行符号需要去掉。
    坑点二:golang是无法直接在二维数组创建时传变量的。这个时候先声明一个二维切片。初始化二维切片后。填入初始值。
    代码实现:

    package main
    
    import (
    	"bufio"
    	"fmt"
    	"io"
    	"os"
    	"strconv"
    	"strings"
    )
    
    func main() {
    	file, err := os.Open("E:/golang开发学习/sparsearray.data")
    	if err != nil {
    		fmt.Printf("打开文件出错:%v", err)
    	}
    	defer file.Close()
    	
    	reader := bufio.NewReader(file)
    	str, err := reader.ReadString('\n')
    	if err == io.EOF { //io.EOF 文件末尾
    		fmt.Println("第一行 读取完毕")
    	}
    	// 分割字符串 通过空格
    	arr := strings.Split(str, " ")
    	m, _ := strconv.Atoi(arr[0])
    	n, _ := strconv.Atoi(arr[1])
    	v, err := strconv.Atoi(strings.Replace(arr[2], "\n", "", -1))
    	if err != nil {
    		// handle error
    		fmt.Println(err)
    		os.Exit(2)
    	}
    	// golang是无法直接在二维数组创建时传变量的 var chessMap [m][n]int 不能成功
    	var chessMap [][]int
    	for i := 0; i < m; i++ {
    		arr1 := make([]int, n)            //创建一个一维切片
    		chessMap = append(chessMap, arr1) //把一维切片,当作一个整体传入二维切片中
    	}
    	for i := 0; i < m; i++ {
    		for j := 0; j < n; j++ {
    			chessMap[i][j] = v
    		}
    	}
    
    	for {
    		str, err := reader.ReadString('\n') // 一次读到换行结束
    		if err == io.EOF {                  //io.EOF 文件末尾
    			break
    		}
    		//输出内容
    		arr := strings.Split(str, " ")
    		m, _ := strconv.Atoi(arr[0])
    		n, _ := strconv.Atoi(arr[1])
    		v, _ := strconv.Atoi(strings.Replace(arr[2], "\n", "", -1))
    		chessMap[m][n] = v
    	}
    	fmt.Println("稀疏数组还原成原数组:")
    	for _, v := range chessMap {
    		for _, v2 := range v {
    			fmt.Printf("%d\t", v2)
    		}
    		fmt.Println()
    	}
    }
    
    • 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
  • 相关阅读:
    1200*C. Make It Good(二分 || 贪心)
    【flex布局】解决:使用justify-content排列,一行四个,最后一行少于四个时,排列不会与上面的对齐
    Transformer模型引领NLP革新之路
    Redis 数据迁移篇之redis-shake工具使用手册
    [附源码]计算机毕业设计JAVA校园飞毛腿系统
    企业怎么找包收录的媒体做推广,便宜又好用的软文发稿平台推荐
    Web 后端的一生之敌:分页器
    JS问题:项目中如何区分使用防抖或节流?
    汽车智能计算平台公司「地平线」在 Ingress Controller 的探索和实践
    链式二叉树的实现及遍历(C语言版)
  • 原文地址:https://blog.csdn.net/ZN175623/article/details/127814615