1. 稀疏数组
稀疏数组(sparsearray) 基本介绍: 当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组。 本质上就是压缩数组。 稀疏数组的处理方法: 1. 记录数组一共有几行几列,有多少个不同的值。 2. 把具有不同值的元素的行列以及值,记录在一个小规模的数组中,从而缩小程序的规模。
1.1 实际问题(棋盘)
如下面的二维数组,我们可以假设成是一个棋盘,1代表白子,2代表黑子,现在我们要对其进行存盘以及续盘的操作,如果我们将整个数组都存起来,势必会造成内存的浪费,那么我们可以考虑使用稀疏数组来解决这个问题。
代码语言:javascript复制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 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 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.1.1 存盘
代码语言:javascript复制func writeSparse() {
// 定义一个结构体,用来存放稀疏矩阵的值
type ValNode struct{
row int // 所在行
col int // 所在列
val int // 值
}
// 定义一个二维数组——棋盘
// 其他都为0
var chessMap [11][11]int
chessMap[1][2] = 1
chessMap[2][3] = 2
// 定义一个切片
var sparseArr []ValNode
// 11行 11列 默认值为0
valNode := ValNode{
row: 11,
col: 11,
val: 0,
}
sparseArr =append(sparseArr,valNode)
// 遍历棋盘,寻找有棋子的地方
for i, v:= range chessMap{
for j, v2:=range v{
if v2 != 0{
// 拿到黑子和白子具体的位置
valNode := ValNode{
row: i,
col: j,
val: v2,
}
sparseArr =append(sparseArr,valNode)
}
}
}
// 存到文件中 便于续盘
filePath := "./数据结构/sparseArr.txt"
file, err := os.OpenFile(filePath,os.O_WRONLY|os.O_CREATE,0666)
// 第一个数字代表u(拥有者)权限,
// 第二个数字代表g(群组)权限,
// 第三个数字代表o(其他人)权限
// 每一个数字都是通过4(表示r),2(表示w),1(表示x)三个数字相加得到的
// rwx 对应4,2,1
// 那么只读的权限用4表示[r--],
// 读写用6(4 2)表示[rw-],
// 读写加执行用7(4 2 1)表示[rwx]。
if err != nil{
fmt.Println("os.OpenFile err:",err)
return
}
// 最终 关闭流
defer file.Close()
// 创建写缓冲区
writer := bufio.NewWriter(file)
// 取出棋子
for _, valNode:=range sparseArr{
str:=fmt.Sprint(valNode.row,valNode.col,valNode.val)
// 写到缓存区中
_, err := writer.WriteString(str "n")
if err != nil{
fmt.Println("writer.WriteString(str) err:",err)
return
}
}
// 刷新数据, 将缓冲区数据写入io writer
writer.Flush()
}
1.1.2 续盘
代码语言:javascript复制func readSparse() {
type ValNode struct {
row int
col int
val int
}
var sparseArr []ValNode
filePath := "./数据结构/sparseArr.txt"
file, err := os.Open(filePath)
if err != nil {
fmt.Println("os.Open(filePath) err:", err)
return
}
defer file.Close()
// 创建读缓冲区
reader := bufio.NewReader(file)
// 读取信息
for{
// 读取delim之前的所有string数据
str,err := reader.ReadString('n')
if err==io.EOF { // io.EOF代表文件的末尾
break
}
fmt.Println(str)
// 返回将字符串按照空白
//(unicode.IsSpace确定, 可以是一到多个连续的空白字符)
// 分割的多个字符串。
// 如果字符串全部是空白或者是空字符串的话,会返回空切片。
arr := strings.Fields(str)
valNode := ValNode{}
for i, _ := range arr {
in,err := strconv.Atoi(arr[i])
if err != nil {
return
}
// arr 中 第一个位置是row 第二个位置是col 第三个位置是val
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
}
}
fmt.Println(chessMap)
}