Go语言数据结构—稀疏数组

Posted 小圣.

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go语言数据结构—稀疏数组相关的知识,希望对你有一定的参考价值。

介绍

如果一个数组中非零个数远远小于数组元素个数,且非零元素分布没有规律,当这样的数组进行存储时,因为很多元素都是为0的,直接存储的话,会浪费掉很多空间。这时候可以数组转化为稀疏数组,然后进行存储。那么怎么进行转换呢?

		0, 1, 0, 0, 0,
		1, 0, 0, 0, 0,
		0, 0, 1, 0, 0,
		0, 0, 0, 0, 0,
		0, 0, 0, 0, 1,
	
以行上面这个数组为例:
	1. 首先记录数组的行、列、几个非零的元素(row、col、value)
	2. 再记录数组存储非零元素的位置和值 (row、col、value)
	3. 最后把row、col、value存储到稀疏数组,并进行保存
	

普通数组转为稀疏数组

函数有两个参数:1. 要转换的数组,2. 转换后稀疏数组的存储路径

func arrayToSparseArray(array [][]int, filePath string) (err error) 

	// 1. 获取稀疏数组的行和列,及非零值的个数
	rowL := len(array)
	colL := len(array[0])
	num := 0
	// 遍历二维数组, 找非零值的数量
	for _, v1 := range array 
		for _, v2 := range v1 
			if v2 != 0 
				num++
			
		
	

	// 声明一个Node的切片,为Node切片类型
	//  Node切片有row、col、value三个属性,用来存储每个非零值元素的信息
	var sparseArr []Node

	// 初始化数组
	node := Node
		rowL,
		colL,
		num,
	
	sparseArr = append(sparseArr, node)

	// 遍历稀疏数组,得到每个非零值信息,并保存到array
	for i, v1 := range array 
		for j, v2 := range v1 
			if v2 != 0 
				node = Nodei, j, v2
				sparseArr = append(sparseArr, node)
			
		
	

	fmt.Println("转换后的数组为:")
	for _, v := range sparseArr 
		fmt.Printf("%d %d %d\\n", v.row, v.col, v.value)
	

	// 把转换后的保存到本地
	file, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY, 0666)
	if err != nil 
		return
	
	defer file.Close()

	writer := bufio.NewWriter(file)
	for _, value := range sparseArr 
		data := fmt.Sprintf("%d %d %d\\n", value.row, value.col, value.value)
		_, err = writer.WriteString(data)
		if err != nil 
			return
		
	
	writer.Flush()

	fmt.Println("写入数据成功")
	return

稀疏数组转为普通数组

函数参数:稀疏文件的存储路径
函数返回值:转换后的普通数组,错误信息

func sparseArrToArr(filePath string) (array [][]int, error error) 
	// 读取本地文件, 获取到稀疏数组
	file, err := os.OpenFile(filePath, os.O_RDONLY, 0666)
	if err != nil 
		error = err
		return
	
	defer file.Close()

	reader := bufio.NewReader(file)
	// 生成稀疏数组
	node := Node
	var row, col, value int
	var sparseArr []Node
	for 
		data, err := reader.ReadString('\\n')
		if err != nil && err != io.EOF 
			error = err
			return
		
		if err == io.EOF 
			break
		
		data2 := strings.Fields(data)
		// 这里读取到的数据为string类型,要转换为int类型
		row, err = strconv.Atoi(data2[0])
		if err != nil 
			error = err
			return
		
		col, err = strconv.Atoi(data2[1])
		if err != nil 
			error = err
			return
		
		value, err = strconv.Atoi(data2[2])
		if err != nil 
			error = err
			return
		
		node = Noderow, col, value
		sparseArr = append(sparseArr, node)
	

	// 遍历稀疏数组,把稀疏数组转化为二维切片
	for i, v := range sparseArr 
		// 稀疏的第0号元素为数组的结构信息
		if i == 0 
			row = v.row
			col = v.col
			array = make([][]int, row)
			for i := range array 
				array[i] = make([]int, col)
				
			continue
		
		// 为数组对应的位置填充对应的值
		array[v.row][v.col] = v.value
	

	// 返回数组及错误信息
	return array, err

测试

func main() 

	filePath := "./sparseArray.txt"

	// 测试数组
	array := [][]int
		0, 1, 0, 0, 0,
		1, 0, 0, 0, 0,
		0, 0, 1, 0, 0,
		0, 0, 0, 0, 0,
		0, 0, 0, 0, 1,
	

	err := arrayToSparseArray(array, filePath)
	if err != nil 
		fmt.Println(err)
		return
	

	data, err := sparseArrToArr(filePath)
	if err != nil 
		fmt.Println(err)
		return
	
	for _, v := range data 
		fmt.Println(v)
	

最后

个人感觉稀疏数组不仅仅可以用于棋盘中,别的很多地方都能使用到,而且数组中非零元素也不一定非要为1才行。代码中还使用了切片,发现切片确实比数组灵活了许多。完整代码在这里:https://github.com/bigzoro/go_algorithm

如果代码中有不足之处,欢迎评论区指出。

以上是关于Go语言数据结构—稀疏数组的主要内容,如果未能解决你的问题,请参考以下文章

Go 稀疏数组模拟棋盘矩阵

Go 稀疏数组模拟棋盘矩阵

数据结构与算法-稀疏数组

数据结构与算法之java语言实现:稀疏数组

热榜!!!数据结构与算法:C语言版---数组与稀疏矩阵---强势来袭!

热榜!!!数据结构与算法:C语言版---数组与稀疏矩阵---强势来袭!