稀疏数组(SparseArray)(Go)

稀疏数组(SparseArray)介绍
    稀疏数组实质还是数组;由实际案例来引出:编写的五子棋程序中,由存盘退出续上盘的功能;
    当一个数组中大部分元素为0(或其他都是相同的数值)数组时,可以使用稀疏数组来保存该数组;
    稀疏数组的处理方法是
        1.记录数组一共由几行几列,有多少个不同的值。
        2.把具有不同值的元素的行列及值记录在一个小规模的数组中,从而缩小程序的规模;
 
        稀疏数组 ----> 压缩数组
        
代码实现:
package main

import (
	"fmt"
	"bufio"
	"os"
	"io"
	"strings"
	"strconv"
)

type ValNode struct {
	row int 
	col int 
	val int 
}

func main() {
	// 稀疏数组 实际案例  五子棋 存盘退出,续上盘
	
	//步骤1 创建原始二维数组
	var oriMap [11][11]int
	oriMap[1][2] = 1  // 黑子
	oriMap[2][3] = 2  // 白子

	// 步骤2 遍历看原始二维数组
	for _, v := range oriMap {
		for _, v2 := range v {
			fmt.Printf("%d\t", v2)
		}
		fmt.Println()
	}

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

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

	var sparseArray []ValNode

	valNode := ValNode{
		row : 11,
		col : 11,
		val : 0,
	}
	sparseArray = append(sparseArray, valNode)

	for i, v := range oriMap {
		for j, v2 := range v {
			if v2 != 0 {
				// 创建一个ValNode 值节点
				valNode := ValNode{
					row : i,
					col : j,
					val : v2,
				}
				sparseArray = append(sparseArray, valNode)
			}
		}
	}
	filePath := "e:/chess_data.txt"
	file, err := os.OpenFile(filePath, os.O_WRONLY | os.O_CREATE, 0666)
	if err != nil {
		fmt.Println("open file err=", err)
		return 
	}
	// 及时关闭file句柄
	defer file.Close()

	// 写入时,使用带缓存的 *Writer
	writer := bufio.NewWriter(file)
	
	// 输出稀疏数组
	fmt.Println("当前的稀疏数组为::::")
	for i, valn := range sparseArray {
		// 存盘 
		fmt.Printf("%d: %d %d %d \n", i, valn.row, valn.col, valn.val)
		// 写入到文件中 使用带缓冲的
		str := fmt.Sprintf("%d %d %d\n", valn.row, valn.col, valn.val)
		fmt.Println("写入文件的内容:", str)
		writer.WriteString(str)
	}

	writer.Flush()

	// 续上盘 即恢复原始的数组 从文件读取
	file, err = os.Open(filePath)
	if err != nil {
		fmt.Println("open file err=", err)
	}

	fmt.Println("file==",file)

	// 当函数退出时,要及时关闭file
	defer file.Close() 
	// 续上盘 即恢复原始的数组
	reader := bufio.NewReader(file)
	// 先创建一个原始数组
	var chessMap [11][11]int

	// 循环的读取文件的内容
	for {
		flag := true
		str, err := reader.ReadString('\n')  // 读到一个换行就结束 
		if err == io.EOF {  // io.EOF 表示文件的末尾
			break 
		}
		// 赋值
		str = strings.Trim(str, "\n")
		fmt.Printf("%q \n", str)
		str_arry := strings.Split(str, " ")
		if str_arry[len(str_arry)-1] == "0" { // 第一行数据没有多大用处 在golang中
			flag = false
		}
		if flag {
			row, err := strconv.Atoi(str_arry[0])
			if err != nil {
				fmt.Println("str_arry[0] err", err)
			}
			col, err := strconv.Atoi(str_arry[1])
			if err != nil {
				fmt.Println("str_arry[1] err", err)
			}
			val, err := strconv.Atoi(str_arry[2])
			if err != nil {
				fmt.Println("str_arry[2] err", err)
			}
			chessMap[row][col] = val
			// fmt.Printf("%v %v %v \n", str_arry[0], str_arry[1], str_arry[2])
		}
	}
	fmt.Println("文件读取完毕, 原始数组赋值完毕!")

	// 最后遍历chessMap 原始二维数组
	for _, v := range chessMap {
		for _, v2 := range v {
			fmt.Printf("%d\t", v2)
		}
		fmt.Println()
	}
}

  

    
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
posted @ 2021-01-14 16:39  以赛亚  阅读(114)  评论(0编辑  收藏  举报