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)
}
}