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 = Node{i, 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 = Node{row, 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语言数据结构—稀疏数组的主要内容,如果未能解决你的问题,请参考以下文章