0
点赞
收藏
分享

微信扫一扫

Golang数据结构与算法之稀疏矩阵

飞进科技 2022-04-26 阅读 102
golang

前言

先看一个实际的需求:编写的五子棋程序中,有存盘退出和续盘恢复的功能:

在这里插入图片描述

1.需求分析:

分析按照原始的方式来的二维数组的问题,因为该二维数组的很多值是默认值 0, 因此记录了很多没有意义的数据。稀疏数组的处理方法是:
1) 记录数组一共有几行几列,有多少个不同的值 。
2) 把具有不同值的元素的行列及值记录在一个小规模的数组中,从而缩小程序的规模。
3) 把稀疏数组存盘,并且可以从新恢复原来的二维数组数。

在这里插入图片描述

2、代码实现

代码如下(示例):

package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strconv"
	"strings"
)
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 _,j := range v {
			fmt.Printf("%d\t",j)
		}
		fmt.Println()
	}
	//3. 转成稀疏数组。
	//(1). 遍历 chessMap, 如果我们发现有一个元素的值不为 0,创建一个 node 结构体
	//(2). 将其放入到对应的切片即可
	var sparseArr []ValNode
	//标准的一个稀疏数组应该还有一个 记录元素的二维数组的规模(行和列,默认值)
	//创建一个 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.txt
	filePath := "d:/chessMap.txt"
	file,err := os.OpenFile(filePath,os.O_WRONLY | os.O_CREATE,0666)
	if err != nil {
		fmt.Println("OpenFile err = ",err)
	}
	defer file.Close()
	writer := bufio.NewWriter(file)
	for _, valNode := range sparseArr {
		writer.WriteString(fmt.Sprintf("%d %d %d\r\n",valNode.row,valNode.col,valNode.val))
	}
	//必须将缓冲区的数据写入文件,否则导致文件不会被写入
	writer.Flush()

	//如何恢复原始的数组
	//1. 打开这个 d:/chessMap.data => 恢复原始数组.
	file2,err := os.Open("d:/chessMap.txt")
	if err != nil {
		fmt.Println("file2 Open fail err = ",err)
	}
	defer file2.Close()
	//创建一个reader
	reader := bufio.NewReader(file2)
	var sparseArr1 []ValNode
	for {
		str, err := reader.ReadString('\n')
		if err == io.EOF { // io.EOF表示文件的末尾
			break
		}
		//strings.Fields()返回将字符串按照空白分割的多个字符串。
		//如果字符串全部是空白或者是空字符串的话,会返回空切片。
		arr := strings.Fields(str)
		valNode := ValNode{}
		for i, _ := range arr {
			in, err := strconv.Atoi(arr[i])//转成int类型
			if err != nil {
				return
			}
			switch i {
				case 0:
					valNode.row = in
				case 1:
					valNode.col = in
				case 2:
					valNode.val = in
			}
		}
		sparseArr1 = append(sparseArr1, valNode)
	}

	// 将稀疏数组还原成二维数组
	var chessMap2 [][]int
	for i, v := range sparseArr {
		if i == 0 {
			for a := 0; a < v.row; a++ {
				mm := make([]int, v.col)
				chessMap2 = append(chessMap2, mm)
			}
		} else {
			chessMap2[v.row][v.col] = v.val
		}
	}
	//打印二维数组
	fmt.Println(chessMap2)
	for _, v := range chessMap2 {
		for _, v1 := range v {
			fmt.Printf("%d\t",v1)
		}
		fmt.Println()
	}
}

代码执行结果如下:

当前的稀疏数组是:
0: 11 11 0
1: 1 2 1
2: 2 3 2
复盘结果为:
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


举报

相关推荐

0 条评论