稀疏矩阵进行三元组压缩存储(golang实现)

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

2、把稀疏数组存盘(文件存储),并且可以重新恢复原来的二维数组

package main

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

type ValNode struct {
	row int
	col int
	val int
}

var (
	//三元组节点
	sparseArr []ValNode
	//初始棋盘数组
	chessMap [11][11]int
)

func init() {
	chessMap[1][2] = 1 //黑子
	chessMap[3][2] = 1 //黑子
	chessMap[2][2] = 1 //黑子
	chessMap[4][2] = 1 //黑子
	chessMap[5][2] = 1 //黑子
	chessMap[6][2] = 1 //黑子
	chessMap[7][2] = 1 //黑子
	chessMap[8][2] = 1 //黑子
	chessMap[2][3] = 2 //白子

	//生成三元组初始规模节点
	valNode := ValNode{
		row: 11,
		col: 11,
		val: 0,
	}
	sparseArr = append(sparseArr, valNode)

	//输出查看原始数组
	fmt.Println("初始棋盘数组")
	for _, v := range chessMap {
		for _, u := range v {
			fmt.Printf("%d\t", u)
		}
		fmt.Println()
	}
	changeArr()
}

//写入文件
func writeFile(file *os.File) {
	//开始写入文件	lock.Lock()
	writer := bufio.NewWriter(file)
	//遍历写入
	for _, v := range sparseArr {
		info := strconv.Itoa(v.row) + " " + strconv.Itoa(v.col) + " " + strconv.Itoa(v.val) + " "
		//info = fmt.Sprintf(info)
		//fmt.Printf("info=%s", info)
		writer.WriteString(info + "\n")
	}
	writer.Flush()
	fmt.Println("写入完毕")
}

//读出文件并存入新的批判数组
func readFile(file *os.File) []ValNode {
	var sparseArr2 []ValNode
	reader := bufio.NewReader(file)
	for {
		str, err := reader.ReadString('\n')
		if err == io.EOF {
			break
		}
		if str != "" {
			info := strings.Split(str, " ")
			row1, _ := strconv.Atoi(info[0])
			col1, _ := strconv.Atoi(info[1])
			val1, _ := strconv.Atoi(info[2])
			valNode := ValNode{
				row: row1,
				col: col1,
				val: val1,
			}
			sparseArr2 = append(sparseArr2, valNode)
		}
	}
	return sparseArr2
}

//记录初始信息写入三元组节点
func changeArr() {
	for i, v := range chessMap {
		for j, u := range v {
			if u != 0 {
				//非空节点就创建一个新的三元组
				valNode := ValNode{
					row: i,
					col: j,
					val: u,
				}
				sparseArr = append(sparseArr, valNode)
			}
		}

	}
}

//从三元组复原棋盘数组
func returnArr(sparseArr []ValNode) [11][11]int {
	var chessMap [11][11]int
	for _, v := range sparseArr {
		//把三元组第一个范围信息节点去除
		if v.val != 0 {
			chessMap[v.row][v.col] = v.val
		}

	}
	return chessMap
}

//打开文件,获取句柄
func openFile(filepath string) *os.File {
	file, err := os.OpenFile(filepath, os.O_RDWR|os.O_CREATE, 0755)
	if err != nil {
		fmt.Printf("open file err=%v\n", err)
	}
	return file
}
func main() {
	//存储文件的地址
	filepath := "D:/Desktop/sparseArry.txt"
	file := openFile(filepath)
	//延时关闭文件
	defer file.Close()

	//将原始数组写入文件存储
	writeFile(file)

	//读取文件获得三元组切片
	sparseArr2 := readFile(file)

	//复原棋盘数组
	chessMap2 := returnArr(sparseArr2)

	//输出复原数组
	fmt.Println("复原后数组")
	for _, v := range chessMap2 {
		for _, u := range v {
			fmt.Printf("%d\t", u)
		}
		fmt.Println()
	}

}

初始稀疏数组如下

初始棋盘数组
0	0	0	0	0	0	0	0	0	0	0	
0	0	1	0	0	0	0	0	0	0	0	
0	0	1	2	0	0	0	0	0	0	0	
0	0	1	0	0	0	0	0	0	0	0	
0	0	1	0	0	0	0	0	0	0	0	
0	0	1	0	0	0	0	0	0	0	0	
0	0	1	0	0	0	0	0	0	0	0	
0	0	1	0	0	0	0	0	0	0	0	
0	0	1	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	

实现后出现问题:在一次运行中,无法实现先存后取,可以写入文件并存储,但是无法读取。但如果不进行存储,只进行读取文件,就可以读到内容。我怀疑是文件读写是对于文件内容缓存的访问出现了执行顺序问题,但是我在使用了信号量机制后,还是没有解决,所以暂时存疑,等待以后解答。

发布了28 篇原创文章 · 获赞 18 · 访问量 3743

猜你喜欢

转载自blog.csdn.net/Aaron_Kings/article/details/105246659