Go数据结构

1. 数据结构的介绍

 2. 数据结构和算法的关系

 3. 稀疏数组

package main

import (
	"fmt"
)

type ValNode struct {
	row int
	col int
	val int
}

func main() {

	//1. 先创建一个原始数组
	var chessMap [11][11]int
	chessMap[1][2] = 1 //黑子
	chessMap[2][3] = 2 //蓝子

	//2. 输出看看原始的数组
	for _, v := range chessMap {
		for _, v2 := range v {
			fmt.Printf("%d\t", v2)
		}
		fmt.Println()
	}

	//3. 转成稀疏数组
	//思路
	//(1). 遍历 chessMap, 如果我们发现有一个元素的值不为0,创建一个node结构体
	//(2). 将其放入到对应的切片即可

	var sparseArr []ValNode
	//标准的一个稀疏数组应该还有一个 记录元素的二维数组的规模(行和列,默认值)
	//创建一个ValNode 值结点
	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 := ValNode{
					row: i,
					col: j,
					val: v2,
				}
				sparseArr = append(sparseArr, valNode)
			}
		}

	}

	//输出稀疏数组
	fmt.Println("当前的稀疏数组是:::::")
	for i, valNode := range sparseArr {
		fmt.Printf("%d: %d %d %d\n", i, valNode.row, valNode.col, valNode.val)
	}

	//将这个稀疏数组,存盘 d:/chessmap.data

	//如何恢复原始的数组

	//1. 打开这个d:/chessmap.data => 恢复原始数组.

	//2. 这里使用稀疏数组恢复

	// 先创建一个原始数组
	var chessMap2 [11][11]int

	// 遍历 sparseArr [遍历文件每一行]
	for i, valNode := range sparseArr {
		if i != 0 { //跳过第一行记录值
			chessMap2[valNode.row][valNode.col] = valNode.val
		}
	}

	// 看看chessMap2 是不是恢复.
	fmt.Println("恢复后的原始数据......")
	for _, v := range chessMap2 {
		for _, v2 := range v {
			fmt.Printf("%d\t", v2)
		}
		fmt.Println()
	}
}

4. 队列(channel的本质就是队列)

4.1 队列的介绍

 

4.2 数组模拟队列

4.3 非环形队列

 

package main
import (
	"fmt"
	"os"
	"errors"
)

//使用一个结构体管理队列
type Queue struct {
	maxSize int
	array [5]int // 数组=>模拟队列
	front int // 表示指向队列首
	rear int // 表示指向队列的尾部
}

//添加数据到队列
func (this *Queue) AddQueue(val int) (err error) {

	//先判断队列是否已满
	if this.rear == this.maxSize - 1 { //重要重要的提示; rear是队列尾部(含最后元素)
		return errors.New("queue full")
	}

	this.rear++ //rear 后移
	this.array[this.rear] = val
	return
}

//从队列中取出数据
func (this *Queue) GetQueue() (val int, err error) {
	//先判断队列是否为空
	if this.rear == this.front { //队空
		return -1, errors.New("queue empty")
	}
	this.front++
	val = this.array[this.front]
	return val ,err
}

//显示队列, 找到队首,然后到遍历到队尾
func (this *Queue) ShowQueue() {
	fmt.Println("队列当前的情况是:")
	//this.front 不包含队首的元素
	for i := this.front + 1; i <= this.rear; i++ {
		fmt.Printf("array[%d]=%d\t", i, this.array[i])
	}
	fmt.Println()
}



//编写一个主函数测试,测试
func main() {

	//先创建一个队列
	queue := &Queue{
		maxSize : 5,
		front : -1,
		rear : -1,

	}

	var key string
	var val int
	for {
		fmt.Println("1. 输入add 表示添加数据到队列")
		fmt.Println("2. 输入get 表示从队列获取数据")
		fmt.Println("3. 输入show 表示显示队列")
		fmt.Println("4. 输入exit 表示显示队列")

		fmt.Scanln(&key)
		switch key {
		case "add":
			fmt.Println("输入你要入队列数")
			fmt.Scanln(&val)
			err := queue.AddQueue(val)
			if err != nil {
				fmt.Println(err.Error())
			} else {

				fmt.Println("加入队列ok")
			}
		case "get":
			val, err := queue.GetQueue()
			if err != nil {
				fmt.Println(err.Error())
			} else {
				fmt.Println("从队列中取出了一个数=", val)
			}
		case "show":
			queue.ShowQueue()
		case "exit":
			os.Exit(0)
		}
	}
}

4.4 环形队列

分析:

package main
import (
	"fmt"
	"errors"
	"os"
)

//使用一个结构体管理环形队列
type CircleQueue struct {
	maxSize int // 4
	array [5]int // 数组
	head  int //指向队列队首 0
	tail int  //指向队尾 0
}


//入队列 AddQueue(push)  GetQueue(pop)
//入队列
func (this *CircleQueue) Push(val int)  (err error) {
	if this.IsFull() {
		return errors.New("queue full")
	}
	//分析出this.tail 在队列尾部,但是包含最后的元素
	this.array[this.tail] = val //把值给尾部
	this.tail = (this.tail + 1) % this.maxSize
	return
}

//出队列
func (this *CircleQueue) Pop() (val int, err error) {

	if this.IsEmpty() {
		return 0, errors.New("queue empty")
	}
	//取出,head 是指向队首,并且含队首元素
	val = this.array[this.head]
	this.head = (this.head + 1) % this.maxSize
	return
}

//显示队列
func (this *CircleQueue) ListQueue() {

	fmt.Println("环形队列情况如下:")
	//取出当前队列有多少个元素
	size := this.Size()
	if size == 0 {
		fmt.Println("队列为空")
	}

	//设计一个辅助的变量,指向head
	tempHead := this.head
	for i := 0; i < size; i++ {
		fmt.Printf("arr[%d]=%d\t", tempHead, this.array[tempHead])
		tempHead = (tempHead + 1) % this.maxSize
	}
	fmt.Println()
}

//判断环形队列为满
func (this *CircleQueue) IsFull() bool {
	return (this.tail + 1) % this.maxSize == this.head
}
//判断环形队列是空
func (this *CircleQueue) IsEmpty() bool {
	return this.tail == this.head
}
//取出环形队列有多少个元素
func (this *CircleQueue) Size() int {
	//这是一个关键的算法.
	return (this.tail + this.maxSize - this.head ) % this.maxSize
}


func main() {

	//初始化一个环形队列
	queue := &CircleQueue{
		maxSize : 5,
		head : 0,
		tail : 0,
	}

	var key string
	var val int
	for {
		fmt.Println("1. 输入add 表示添加数据到队列")
		fmt.Println("2. 输入get 表示从队列获取数据")
		fmt.Println("3. 输入show 表示显示队列")
		fmt.Println("4. 输入exit 表示显示队列")

		fmt.Scanln(&key)
		switch key {
		case "add":
			fmt.Println("输入你要入队列数")
			fmt.Scanln(&val)
			err := queue.Push(val)
			if err != nil {
				fmt.Println(err.Error())
			} else {

				fmt.Println("加入队列ok")
			}
		case "get":
			val, err := queue.Pop()
			if err != nil {
				fmt.Println(err.Error())
			} else {
				fmt.Println("从队列中取出了一个数=", val)
			}
		case "show":
			queue.ListQueue()
		case "exit":
			os.Exit(0)
		}
	}
}

猜你喜欢

转载自www.cnblogs.com/yzg-14/p/12237405.html