GO语言数据结构之稀疏数组

稀疏数组可以看做是普通数组的压缩

当一个数组中大部分元素为0,或者为同一值的数组时,可以使用稀疏数组来保存该数组。

稀疏数组的处理方式是:记录数组一共有几行几列,有多少个不同值;把具有不同值的元素和行列及值记录在一个小规模的数组中,从而缩小程序的规模

 借用解释稀疏数组最多的例子五子棋来说

 如何将五子棋盘上的黑白子保存下来

用计算机来看将五子棋的棋盘15×15总共225个交点转化为二维数组

[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 0 0 0 0 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 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 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 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]

这样以数组的方式存储会有大量无意义的数据

如果使用稀疏数组则可以简化成这样的

[15 15 4]   //通常稀疏数组的第一行用来记录原二维数组的规模和数据个数
[0 3 1]
[3 4 2]
[6 9 1]
[10 6 2]

那么go语言如何实现稀疏数组

func main() {
	//构建数组
	var a [15][15]int
	//插入棋子
	a[0][3] = 1
	a[3][4] = 2
	a[6][9] = 1
	a[10][6] = 2
	for _, ints := range a {
		fmt.Println(ints)
	}
	fmt.Println("===============分界线===============")
	//计算黑白子的个数
	var amount int = 0
	for _, ints := range a {
		for _, i := range ints {
			if i > 0 {
				amount++
			}
		}
	}
	//计算原数组的行,列
	row := len(a)
	col := len(a[0])

	//构建稀疏数组
	b := make([][3]int, amount+1)
	//定义第一行原数组规格
	b[0][0] = row
	b[0][1] = col
	b[0][2] = amount

	var count int = 0

	//获取原数组的具体内容
	for c, ints := range a {
		for d, i := range ints {
			if i != 0 {
				count++
				b[count][0] = c
				b[count][1] = d
				b[count][2] = a[c][d]
			}
		}
	}
	for _, ints := range b {
		fmt.Println(ints)
	}
	fmt.Println("===============分界线===============")
	//还原原数组
	c := make([][]int, b[0][0])
	//初始化内部切片
	for i := range c {
		c[i] = make([]int, b[0][1])
	}
	for i := 1; i < len(b); i++ {
		c[b[i][0]][b[i][1]] = b[i][2]
	}
	for _, ints := range c {
		fmt.Println(ints)
	}

//写入文件操作
	storage(b)
	fmt.Println("===============分界綫===============")
//读取文件操作,结构体方式
	read()
	fmt.Println("===============分界綫===============")
//读取文件操作,二维切片转换方式
	reads()
}

写入文件操作

func storage(b [][3]int) {
	filePath := "C:\\Users\\zly\\Desktop\\abc.data"
	file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0666)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer func(file *os.File) {
		err := file.Close()
		if err != nil {

		}
	}(file)

	writer := bufio.NewWriter(file)
	for _, ints := range b {
		for _, i := range ints {
			_, err := writer.WriteString(strconv.Itoa(i))
			_, err = writer.WriteString(" ")
			if err != nil {
				return
			}
		}
		_, err := writer.WriteString("\n")
		if err != nil {
			return
		}
	}

	err = writer.Flush()
	if err != nil {
		return
	}
}

读取文件操作

//读取文件,结构体
func read() {
	open, err := os.Open("C:\\Users\\zly\\Desktop\\abc.data")
	if err != nil {
		return
	}
	defer func(open *os.File) {
		err := open.Close()
		if err != nil {

		}
	}(open)
	reader := bufio.NewReader(open)

	type ValNode struct {
		row int
		col int
		val int
	}

	var sparseArr []ValNode

	for {
		sss, err := reader.ReadString('\n')
		if err == io.EOF {
			break
		}
		fmt.Print(sss)
		//根据空格分割字符串
		arr := strings.Fields(sss)
		valNode := ValNode{}
		for i, _ := range arr {
			in, err := strconv.Atoi(arr[i])
			if err != nil {
				return
			}
			switch i {
			case 0:
				valNode.row = in
			case 1:
				valNode.col = in
			case 2:
				valNode.val = in
			}
		}
		sparseArr = append(sparseArr, valNode)

	}
	var chessMap [][]int
	//var chessMap [11][11]int
	for i, v := range sparseArr {
		if i == 0 {

			for a := 0; a < v.row; a++ {
				mm := make([]int, v.col)
				chessMap = append(chessMap, mm)
			}
		} else {
			chessMap[v.row][v.col] = v.val
		}

	}
	for _, ints := range chessMap {
		fmt.Println(ints)
	}
}

//读取文件操作,二维切片
func reads() {
	//读取文件
	open, err := os.Open("C:\\Users\\zly\\Desktop\\abc.data")
	if err != nil {
		return
	}
	defer func(open *os.File) {
		err := open.Close()
		if err != nil {

		}
	}(open)
	reader := bufio.NewReader(open)
	//定义读取内容切片
	var d [][]string
	for {
		sss, err := reader.ReadString('\n')
		if err == io.EOF {
			break
		}
		//根据空格分割字符串
		arr := strings.Fields(sss)
		d = append(d, arr)
	}
	//切片格式转换
	var e [][]int
	for _, i2 := range d {
		var tmp []int
		for _, s := range i2 {
			atoi, err := strconv.Atoi(s)
			if err != nil {
				return
			}
			tmp = append(tmp, atoi)
		}
		e = append(e, tmp)
	}
	fmt.Println(e)
	//还原原数组
	c := make([][]int, e[0][0])
	//初始化内部切片
	for i := range c {
		c[i] = make([]int, e[0][1])
	}
	//从1号索引来遍历稀疏数组
	for i := 1; i < len(e); i++ {
		c[e[i][0]][e[i][1]] = e[i][2]
	}
	for _, ints := range c {
		fmt.Println(ints)
	}
}

posted @ 2021-08-11 18:07  悠悠听风  阅读(75)  评论(0编辑  收藏  举报