数据结构

稀疏数组

func main(){
	var chessMap [11][11]int
	chessMap [1][2] = 1
	chessMap [2][3] = 2
	for _,v:=range chessMap{
		for _,o:= range v{
			fmt.Printf("%v\t",o)
		}
		fmt.Println()
	}
	//转成稀疏数组
	var sparseArr []ValNode
	t := ValNode{
					row: 11,
					col: 11,
					val: 2,
				}
	sparseArr=append(sparseArr,t)
	//标准稀疏数组,应该还有一个表示记录原始的二维数据的规模(行和列,以及默认值)
	for i,v:=range chessMap{
		for r,o:= range v{
			if o !=0{
				t = ValNode{
					row: i,
					col: r,
					val: o,
				}
				sparseArr=append(sparseArr,t)
			}
		}
		//fmt.Println()
	}
	//fmt.Println()
	for i,v:= range sparseArr{
		fmt.Printf("%d:%d %d %d\n",i,v.row,v.col,v.val)
	}
	var chessMap2 [11][11]int
	for i,valNade := range sparseArr{
		if i!=0{
			chessMap2[valNade.row][valNade.col]= valNade.val
		}
	}
	for _,v:=range chessMap2{
		for _,o:= range v{
			fmt.Printf("%v\t",o)
		}
		fmt.Println()
	}
	
}
// 执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter20\demo01\main.go
// 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
// 0:11 11 2
// 1:1 2 1
// 2:2 3 2
// 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. 队列是有序列表,可以用数组或是链表来实现

2.遵循先入先出的原则。即:先存入列队的数据,要先取出,。后存入的要后取出

示例1 

package main
import (
	"errors"
	"fmt"
)
//使用一个数据结构
type Queue struct{
	maxSize int 
	array [5]int
	front int //表示指向数组前面
	rear int //表示指向队列的尾部
}
func (this *Queue)Add(val int) (err error){
	//先判断队列是否已满
	if this.rear > this.maxSize-1{ //重要提示;rear是队列尾部含最后一个元素
		return errors.New("队列已满无法添加")
	}
	this.rear++
	this.array[this.rear]=val
	return err 
}
//显示队列
func (this *Queue)Show(){
  //找到队首遍历到
  for i:= this.front+1 ;i <= this.rear;i++{
	fmt.Println(this.array[i])
  }
}
func (this *Queue)GetQueue() (val int,err error){
	if this.rear == this.front{
		return -1 , errors.New("queue ")

	}
	this.front++
	val= this.array[this.front]
	return val ,err
}
func main(){
	queue := &Queue{
		maxSize: 5,
		front: -1,
		rear: -1,
	}
	// var key string
	// var val int
	for {
		var key string
		var val int
		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.Add(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.Show()
		}
	}

}

  环形队列

package main

import (
	"errors"
	"fmt"
	//"hash"
	"os"
)

//使用一个数据结构
type Queue struct{
	maxSize int 
	array [5]int
	// front int //表示指向数组前面
	// rear int //表示指向队列的尾部
	head int //队首
	tail int //队尾
}
func (t *Queue)Push(val int)(err error){
	if t.IsFull(){
		return errors.New("队列已满")
	}
	//分析出t.tail 在队列尾部,但是不含最后元素
	t.array[t.tail]= val
	t.tail++
	return 

}
func (t *Queue)Pop()(val int,err error){
	if t.IsEmpty(){
		return 0,errors.New("队列已空")
	}
	
	val = t.array[t.head]
	t.head++
	return 

}
//判断
func (t *Queue)IsFull() bool{
	return (t.tail+1)%t.maxSize== t.head

	
}
//判断队列为空
func (t *Queue)IsEmpty()bool{
	return  t.tail == t.head
}
//取出队列多少元素
func (t *Queue)Size()int{
	//关键
	return  (t.tail +t.maxSize-t.head)%t.maxSize
}
func (t *Queue)ListQueue(){
	size :=t.Size()
	if size ==0{
		fmt.Println("队列为空")
		return
	}
	tempHead := t.head
	for i:=0;i<size;i++{
		
		fmt.Printf("arr[%d]=%d\t", tempHead,t.array[tempHead])
		tempHead= (tempHead+1)%t.maxSize
	}
	
	
	fmt.Println()
}
func main(){
	queue := &Queue{
		maxSize: 5,
		head: 0,
		tail: 0, 
	}
		for {
		var key string
		var val int
		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)
		}
	}
	
}
// 执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter20\demo03\main.go
// 1. 输入add 表示添加数据到队列
// 2. 输入get 表示从队列获取数据
// 3. 输入show 表示显示队列
// 4. 输入exit 表示显示队列
// add
// 输入你要入队列数
// 1
// 加入队列ok 
// 1. 输入add 表示添加数据到队列
// 2. 输入get 表示从队列获取数据
// 3. 输入show 表示显示队列
// 4. 输入exit 表示显示队列
// add
// 输入你要入队列数
// 2
// 加入队列ok 
// 1. 输入add 表示添加数据到队列
// 2. 输入get 表示从队列获取数据
// 3. 输入show 表示显示队列
// 4. 输入exit 表示显示队列
// add
// 输入你要入队列数
// 3
// 加入队列ok 
// 1. 输入add 表示添加数据到队列
// 2. 输入get 表示从队列获取数据
// 3. 输入show 表示显示队列
// 4. 输入exit 表示显示队列
// add
// 输入你要入队列数
// 5
// 加入队列ok 
// 1. 输入add 表示添加数据到队列
// 2. 输入get 表示从队列获取数据
// 3. 输入show 表示显示队列
// 4. 输入exit 表示显示队列
// show
// arr[0]=1        arr[1]=2        arr[2]=3        arr[3]=5
// 1. 输入add 表示添加数据到队列
// 2. 输入get 表示从队列获取数据
// 3. 输入show 表示显示队列
// 4. 输入exit 表示显示队列
// get 
// 1
// 1. 输入add 表示添加数据到队列
// 2. 输入get 表示从队列获取数据
// 3. 输入show 表示显示队列
// 4. 输入exit 表示显示队列
// add 
// 输入你要入队列数
// 4
// 加入队列ok 
// 1. 输入add 表示添加数据到队列
// 2. 输入get 表示从队列获取数据
// 3. 输入show 表示显示队列
// 4. 输入exit 表示显示队列
// add
// 输入你要入队列数
// 6
// 队列已满
// 1. 输入add 表示添加数据到队列
// 2. 输入get 表示从队列获取数据
// 3. 输入show 表示显示队列
// 4. 输入exit 表示显示队列
// show
// arr[1]=2        arr[2]=3        arr[3]=5        arr[4]=4
// 1. 输入add 表示添加数据到队列
// 2. 输入get 表示从队列获取数据
// 3. 输入show 表示显示队列
// 4. 输入exit 表示显示队列

  链表 

链表介绍: 是有序的列表,但是它在内存中存储如下

image

单链表结构

image

单链表的示意图

说明: 一般来说,为了比较好的对链表进行增删改查操作,设置一个头结点,一般表示链表的头,作用标识链表头,本身节点不存放数据

 

package main

import (
	//"errors"
	"fmt"
	//"hash"
	//"os"
)
//node
type HeroNode struct{
	no int
	name string
	nickname string
	next *HeroNode
}
//给链表插入节点
func InsertHeroNode(head *HeroNode,h1 *HeroNode){
	//找到链表最后一个节点
	//创建一个辅助节点
	temp := head
	for {
		if temp.next==nil{// 表示找到最后
			break
		}
		temp = temp.next//不断指向下一个节点
	}
	temp.next= h1
}
func InsertHeroNode2(head *HeroNode,h1 *HeroNode){
	//找到链表适当节点
	//创建一个辅助节点
	temp := head
	flag := true
	for  {
		// if temp.next==nil{// 表示找到最后
		// 	break
		// }
		// temp = temp.next//不断指向下一个节点
		if temp.next ==nil{//到链表最后
			break
		}else if temp.next.no> h1.no{
			//说明h1 应该插入temp后面
			break
			//temp.next=h1
		}else if temp.next.no== h1.no{
			//fmt.Println("错误不允许插入")
			flag = false
			break
		}
		temp= temp.next
	}
	if  !flag {
		fmt.Println("对不起已经存在英雄")
		return
	}else{
		h1.next= temp.next
		temp.next= h1
	}
	temp.next= h1
}
//显示链表所有信息
func ListLink(head *HeroNode){
	//
	temp := head
	//判断链表是不是空链表
	if temp.next== nil{
		fmt.Println("空链表")
		return
	}
	for {
		fmt.Printf("[%d ,%s,%s]===>\n",temp.next.no,temp.next.name,temp.next.nickname)
		temp= temp.next
		if temp.next== nil{
			fmt.Println("链表显示完成")
			break
		}	
	}
}
func main()	{
	head:= &HeroNode{
	}
	head1 := &HeroNode{
		no: 1,
		name: "宋江",
		nickname: "及时雨",

	}
	head2 := &HeroNode{
		no: 2,
		name: "卢俊义",
		nickname: "玉麒麟",

	}
	head3 := &HeroNode{
		no: 3,
		name: "林冲",
		nickname: "豹子头",

	}
	
	InsertHeroNode2(head,head3)
	InsertHeroNode2(head,head1)
	InsertHeroNode2(head,head2)

	ListLink(head)
}
	

//执行结构
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter20\demo04\main.go
// [1 ,宋江,及时雨]===>
// [2 ,卢俊义,玉麒麟]===>
// [3 ,林冲,豹子头]===>
// 链表显示完成

  删除节点

 

package main

import (
	//"errors"
	"fmt"
	//"text/template"
	//"hash"
	//"os"
)

//node
type HeroNode struct{
	no int
	name string
	nickname string
	next *HeroNode
}
//删除节点
func DelHerNode(head *HeroNode,id int){
	temp:= head
	flag:= false
		for  {
		if temp.next ==nil{//到链表最后
			break
		}else if temp.next.no== id{
			//fmt.Println("错误不允许插入")
			flag = true
			break
		}
		temp= temp.next
	}

	if  flag {
		temp.next= temp.next.next
	}else {
		fmt.Println("删除ID不存在")
	}

}
//给链表插入节点
func InsertHeroNode(head *HeroNode,h1 *HeroNode){
	//找到链表最后一个节点
	//创建一个辅助节点
	temp := head
	for {
		if temp.next==nil{// 表示找到最后
			break
		}
		temp = temp.next//不断指向下一个节点
	}
	temp.next= h1
}
func InsertHeroNode2(head *HeroNode,h1 *HeroNode){
	//找到链表适当节点
	//创建一个辅助节点
	temp := head
	flag := true
	for  {
		// if temp.next==nil{// 表示找到最后
		// 	break
		// }
		// temp = temp.next//不断指向下一个节点
		if temp.next ==nil{//到链表最后
			break
		}else if temp.next.no> h1.no{
			//说明h1 应该插入temp后面
			break
			//temp.next=h1
		}else if temp.next.no== h1.no{
			//fmt.Println("错误不允许插入")
			flag = false
			break
		}
		temp= temp.next
	}
	if  !flag {
		fmt.Println("对不起已经存在英雄")
		return
	}else{
		h1.next= temp.next
		temp.next= h1
	}
	temp.next= h1
}
//显示链表所有信息
func ListLink(head *HeroNode){
	//
	temp := head
	//判断链表是不是空链表
	if temp.next== nil{
		fmt.Println("空链表")
		return
	}
	for {
		fmt.Printf("[%d ,%s,%s]===>\n",temp.next.no,temp.next.name,temp.next.nickname)
		temp= temp.next
		if temp.next== nil{
			fmt.Println("链表显示完成")
			break
		}	
	}
}
func main()	{
	head:= &HeroNode{
	}
	head1 := &HeroNode{
		no: 1,
		name: "宋江",
		nickname: "及时雨",

	}
	head2 := &HeroNode{
		no: 2,
		name: "卢俊义",
		nickname: "玉麒麟",

	}
	head3 := &HeroNode{
		no: 3,
		name: "林冲",
		nickname: "豹子头",

	}
	
	InsertHeroNode2(head,head3)
	InsertHeroNode2(head,head1)
	InsertHeroNode2(head,head2)
	ListLink(head)
	DelHerNode(head,2)

	ListLink(head)
}
	

//执行结构
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter20\demo04\main.go
// [1 ,宋江,及时雨]===>
// [2 ,卢俊义,玉麒麟]===>
// [3 ,林冲,豹子头]===>
// 链表显示完成
// [1 ,宋江,及时雨]===>
// [3 ,林冲,豹子头]===>
// 链表显示完成

  双向链表

介绍:使用带head 头的双向链表实现,

1)单向链表,查找只能是一个方向,而双向链表可以向前或向后查找

2)单向链表不能自我删除,需要辅助节点,而双向链表则可以自我删除,所以前面单向链表删除时,总是找到temp 的下一个节点来删除

 

package main

import (
	//"errors"
	"fmt"
	//"text/template"
	//"hash"
	//"os"
)

//node
type HeroNode struct{
	no int
	name string
	nickname string
	next *HeroNode
	pre *HeroNode
}
//删除节点
func DelHerNode(head *HeroNode,id int){
	temp:= head
	flag:= false
		for  {
		if temp.next ==nil{//到链表最后
			break
		}else if temp.next.no== id{
			//fmt.Println("错误不允许插入")
			flag = true
			break
		}
		temp= temp.next
	}

	if  flag {
		temp.next= temp.next.next
		if temp.next!=nil {
			temp.next.pre=temp
		}
		
	}else {
		fmt.Println("删除ID不存在")
	}

}
//给链表插入节点
// 给双向链表添加一个节点
func InsertHeroNode(head *HeroNode,h1 *HeroNode){
	//找到链表最后一个节点
	//创建一个辅助节点
	temp := head
	for {
		if temp.next==nil{// 表示找到最后
			break
		}
		temp = temp.next//不断指向下一个节点
	}
	temp.next= h1
	h1.pre= temp
}
func InsertHeroNode2(head *HeroNode,h1 *HeroNode){
	//找到链表适当节点
	//创建一个辅助节点
	temp := head
	flag := true
	for  {
		// if temp.next==nil{// 表示找到最后
		// 	break
		// }
		// temp = temp.next//不断指向下一个节点
		if temp.next ==nil{//到链表最后
			break
		}else if temp.next.no> h1.no{
			//说明h1 应该插入temp后面
			break
			//temp.next=h1
		}else if temp.next.no== h1.no{
			//fmt.Println("错误不允许插入")
			flag = false
			break
		}
		temp= temp.next
	}
	if  !flag {
		fmt.Println("对不起已经存在英雄")
		return
	}else{
		h1.next= temp.next
		//
		h1.pre=temp
		if temp.next!=nil {
		temp.next.pre=h1
		
		}
		temp.next= h1
	}
	temp.next= h1
	h1.pre= temp
}
//显示链表所有信息
func ListLink(head *HeroNode){
	//
	temp := head
	//判断链表是不是空链表
	if temp.next== nil{
		fmt.Println("空链表")
		return
	}
	for {
		fmt.Printf("[%d ,%s,%s]===>\n",temp.next.no,temp.next.name,temp.next.nickname)
		temp= temp.next
		if temp.next== nil{
			fmt.Println("链表显示完成")
			break
		}	
	}
}
func ListLink2(head *HeroNode){
	//
	temp := head
	//判断链表是不是空链表
	if temp.next== nil{
		fmt.Println("空链表")
		return
	}
	for{
		if temp.next==nil{
			break
		}
		temp= temp.next
	}

	for {
		fmt.Printf("[%d ,%s,%s]===>\n",temp.no,temp.name,temp.nickname)
		temp= temp.pre

		if temp.pre== nil{
			fmt.Println("链表显示完成")
			break
		}	
	}
}

func main()	{
	head:= &HeroNode{
	}
	head1 := &HeroNode{
		no: 1,
		name: "宋江",
		nickname: "及时雨",

	}
	head2 := &HeroNode{
		no: 2,
		name: "卢俊义",
		nickname: "玉麒麟",

	} 
	head3 := &HeroNode{
		no: 3,
		name: "林冲",
		nickname: "豹子头",

	}
	
	InsertHeroNode(head,head1)
	InsertHeroNode(head,head2)
	InsertHeroNode(head,head3)
	ListLink(head)

	ListLink2(head)
	fmt.Println("***")
}

  环形链表

 

package main

import (
	//"crypto/cipher"
	"fmt"
	//"github.com/redis/go-redis/v9/helper"
)
type Boy struct{
	No int
	Next *Boy
}
//编写函数,构成环形链表
//num 表示小孩个数
//Boy:返回该环形的链表的第一个小孩指针
func AddBoy(num int) *Boy{
	CurBoy := &Boy{}
	first := &Boy{}//空
	if num<1{
		fmt.Println("num的值")
		return first
	}
	//循环构建环形链表
	for i:=1;i<=num;i++{
		boy := &Boy{
			No: i,
		}
		//构成循环列表需要赋值指针

		//因为第一个小孩比较特殊
		if i==1{
			//boy.Next=boy
			first = boy
			CurBoy = boy
			CurBoy.Next = first//形成一个循环
		}else{
			CurBoy.Next=boy
			//CurBoy.Next.No=CurBoy.No+1
			CurBoy= boy
			CurBoy.Next=first
		}
	}
	return  first
}
//分析思路
// 1.编写一个函数


func ShowBoy(first *Boy){
	if first.Next==nil {
		fmt.Println("是一个空链表")
		return
	}
	//创建指针帮助遍历
	CurBoy := first
	for{
		// if CurBoy.Next==first{
		// 	fmt.Printf("小孩编号=%d\n",CurBoy.No)
		// 	break
		// }else{
		// 	fmt.Printf("小孩编号=%d\n",CurBoy.No)
		// 	CurBoy=CurBoy.Next
		// }
		fmt.Printf("小孩编号=%d\n",CurBoy.No)
		if CurBoy.Next== first{
			break
		}
		CurBoy= CurBoy.Next
	}	
	

}
//编写一个函数,PlayGame(first *Boy,startNo int,countNum int)
//最后使用环形链表留下最后一个人

func PlayGame(first *Boy,startNo int,countNum int){
	//需要定辅助节点。 帮助帮助我们删除删除小孩的一个,这是刚才说还有一个情况也是这样的,如果上来过这个空,如果是空的那个空的表就可以了,有问题空表呢,单独一下空的链表,链表,我们单独的出一下单独处理,这个很简单,那就意思,如果我们进来投机里的,那他等于is near说明它是空的列表就没法没法玩,所以放一个控制好。
	//如果这个是一个空列表。 我们就要单独处理
	if first.Next==nil{
		fmt.Println("空")
		return
	}
	//留一个判断。 参数是否大于小孩总数
	tail := first
	// Tail指向环形链表的最后一个。
	//因为tail在删除小孩子使需要用到。
	for{
		if tail.Next==first{
			break
		}
		tail=tail.Next
	}
	for i:=1;i<= startNo-1;i++{
		first = first.Next
		tail= tail.Next
	}
	for {
		// 开始数countNum-1
		for i:=1; i<=countNum-1;i++{
			first = first.Next
			tail= tail.Next
		}
		//删除first 执行的小孩
		fmt.Printf("小孩编号为%d\n",first.No)
		first = first.Next
		tail.Next = first
		if first== tail{
			break
		}
	}
	fmt.Printf("小孩编号为%d 出圈->\n",first.No)
 }

func main(){
	first := AddBoy(5)
	ShowBoy(first)
	PlayGame(first,2,3)
}
//执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter20\demo07\main.go
// 小孩编号=1
// 小孩编号=2
// 小孩编号=3
// 小孩编号=4
// 小孩编号=5
// 小孩编号为4
// 小孩编号为2
// 小孩编号为1
// 小孩编号为3
// 小孩编号为5 出圈->

  排序

排序是将一组数据,依指定的顺序进行排列的过程

1)冒泡排序

2)选择排序

3)插入排序

4)快速排序

排序

选择排序思想:

package main

import (
	//"crypto/cipher"
	"fmt"
	//"github.com/redis/go-redis/v9/helper"
)

func SelectSort(arr *[5]int){
	//arr[1]=600
	for x:=0;x<len(arr)-1;x++{
		max :=arr[x]
		maxIndex :=x
		for i:=x+1;i<len(arr);i++{
			if max < arr[i]{
				max=arr[i]
				maxIndex=i
				// arr[maxIndex]=arr[i]
			}
		}
		if maxIndex != x{
			arr[x],arr[maxIndex] = arr[maxIndex],arr[x]
		}
		fmt.Printf("第%d次交换结构结果;%d;\n",x,*arr)
	}
}
func main(){
	arr := [5]int{10,34,19,100,80}
	SelectSort(&arr)
	fmt.Println("main")
	fmt.Println(arr)
}
//执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter20\demo08\main.go
// 第0次交换结构结果;[100 34 19 10 80];
// 第1次交换结构结果;[100 80 19 10 34];
// 第2次交换结构结果;[100 80 34 10 19];
// 第3次交换结构结果;[100 80 34 19 10];
// main
// [100 80 34 19 10]

  插入排序介绍: 插入排序属于内部排序,是对于欲排序的元素以插入的方式找寻该元素的适当位置,以达到排序的目的;思想:把n个待排序的元素看成为一个有序列表和一个无序列表,开始时有序列表只包含一个元素,无序列表包含有n-1个元素,排序过程中每次从无序列表中取出第一个元素,把它的排序码依次进行比较,将他插入到有序列表中的适当位置。使之成为新的有序表

image

 示例

package main

import (
	"fmt"
)
func InsertSort(arr *[5]int){
	// insertVal:=arr[1]
	// insertIdex:=1-1//下标
	for i :=1;i<len(arr);i++{
		insertVal:=arr[i]
		insertIdex:=i-1//下标
		for insertIdex>=0&& arr[insertIdex]<insertVal{
		// if arr[insertIdex]< insertVal{
		// 	arr[insertIdex]=arr[insertIdex+1]
		// }
			arr[insertIdex+1]=arr[insertIdex]
			insertIdex--
		}
		if insertIdex+1!=insertIdex{
		arr[insertIdex+1]=insertVal
		}
		fmt.Printf("第%d次,%d\n",i,*arr)
	}
}
func main(){
  arr:=[5]int{23,0,12,56,34}
  InsertSort(&arr)
}
//执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter20\demo09\main.go
// 第1次,[23 0 12 56 34]
// 第2次,[23 12 0 56 34]
// 第3次,[56 23 12 0 34]
// 第4次,[56 34 23 12 0]

  快速排序法

快速排序是对冒泡排序的一种该进。基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另一部分的所有数据都要小,然后按照次方法对这两部分数据分别进行快速排序。整个排序过程可以递归进行,依次达到整个数据变成有序序列

image

 

package main

import (
	"fmt"
	//"testing/quick"
)
//最左边下标left
//右边下标right
func QuickSort(left int,right int,array *[6]int){
	l := left
	r := right
	//中轴
	pivot := array[(left+right)/2]
	//temp:=0
	//比pivot 小的数放到左边
	//比pivot 大的数放到右边

	for;l<r;{
		for ; array[l]<pivot;{
			l++
		}
		for ;array[r]>pivot;{
			r--
		}
		//表示
		if l>=r{
			break
		}
		// temp = array[l]
		// array[l]= array[r]
		// array[r]=temp
		array[l],array[r]=array[r],array[l]
		if array[l]==pivot{
			r--
		}
		if array[r]==pivot{
			l++
		}
	}

	if l==r{
		l++
		r--
	}
	//向做
	if left<r{
		QuickSort(left,r,array)
	}
	if right>l{
		QuickSort(l,right,array)
	}


}
func main(){
  arr:=[6]int{-9,78,0,23,-567,70}
  fmt.Println(arr)
  QuickSort(0,5,&arr)
 fmt.Println(arr)
  //InsertSort(&arr)
}
// 执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter20\demo10\main.go
// [-9 78 0 23 -567 70]
// [-567 -9 0 23 70 78]

  栈

也有人称栈为堆栈,即栈和堆栈是一个概念;栈的英文(stack);栈是一个先入后出(FILO-First IN Last Out)的有序列表。栈是限制线性表中元素的插入和删除只能在线性表同一端进行的一种特殊线性表,允许插入和删除的一端。为变化一端称为栈顶,另一端为固定的一端,成为栈底;根据堆栈的定义可知,最先放入栈中元素在栈底,最后放入的元素在栈顶,而删除元素则刚刚相反,最后放入的元素先被删除,最先放入的元素最后删除

image

应用场景

1)子程序的调用。在跳往子程序前,会先将下一个指令地址存到栈中,直到子程序执行完后将地址取出,以回到原来的程序中

2)处理递归调用: 和子程序的调用类似,只是除了存储下一个指令的地址外,也将参数区域变量等数据存入堆栈中

3)表达式的转换与求值

4)二叉树的遍历

5)图形的深度优先(depth-first)搜索法

栈的入门

1)用数组模拟栈的使用,由于堆栈是一种有序列表,当然可以使用数组的结构来存储栈的数据内容,下面我们就用数组模拟栈的出栈。入栈等操作

2)实现思路分析图,并画出

image

 入栈和遍历

package main

import (
	"errors"
	"fmt"
	//"testing/quick"
)

//最左边下标left
//右边下标right
type Stack struct{
	MaxTop int //表示我们栈最大可以存放个数
	Top int //表示栈顶
	arr [5]int
}
func (this *Stack)push(val int) (err error){
	// 
	if this.Top==this.MaxTop-1{
		fmt.Printf("栈满")
		return errors.New("栈满溢出")
	}
	this.Top++
	this.arr[this.Top]=val
	return

}
//遍历栈时需要从栈顶开始遍历
func (this *Stack)list(){
	//判断栈是否为空
	if this.Top==-1{
		fmt.Println("是一个空栈")
	}
//	curTop = this.Top
	for i:=this.Top;i>=0;i--{
		fmt.Printf("arr[%d]=%d\n",i,this.arr[i])
	}
}
func main(){
	stack:=&Stack{
		MaxTop: 5,
		Top: -1,
	}
	stack.push(1)
	stack.push(2)
	stack.push(3)
	stack.push(4)
	stack.push(5)
	stack.list()

}
// 执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter20\demo11\main.go
// arr[4]=5
// arr[3]=4
// arr[2]=3
// arr[1]=2
// arr[0]=1

  出栈

package main

import (
	"errors"
	"fmt"
	//"testing/quick"
)

//最左边下标left
//右边下标right
type Stack struct{
	MaxTop int //表示我们栈最大可以存放个数
	Top int //表示栈顶
	arr [5]int
}
func (this *Stack)push(val int) (err error){
	// 
	if this.Top==this.MaxTop-1{
		fmt.Printf("栈满")
		return errors.New("栈满溢出")
	}
	this.Top++
	this.arr[this.Top]=val
	return

}
func (this *Stack)Pop() (val int,err error){
	if this.Top==-1{
		fmt.Println("空栈")
		//val = -2
		return -2, errors.New("栈空")
	}
	val = this.arr[this.Top]
	this.Top--
	return val,nil
}
//遍历栈时需要从栈顶开始遍历
func (this *Stack)list(){
	//判断栈是否为空
	if this.Top==-1{
		fmt.Println("是一个空栈")
	}
//	curTop = this.Top
	for i:=this.Top;i>=0;i--{
		fmt.Printf("arr[%d]=%d\n",i,this.arr[i])
	}
}
func main(){
	stack:=&Stack{
		MaxTop: 5,
		Top: -1,
	}
	stack.push(1)
	stack.push(2)
	stack.push(3)
	stack.push(4)
	stack.push(5)
	stack.list()
	val,_:=stack.Pop()
	fmt.Println("出栈val=",val)
	stack.list()
}
// 执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter20\demo11\main.go
// arr[4]=5
// arr[3]=4
// arr[2]=3
// arr[1]=2
// arr[0]=1
// 出栈val= 5
// arr[3]=4
// arr[2]=3
// arr[1]=2
// arr[0]=1

  计算分析

image

一位数计算

package main

import (
	"errors"
	"fmt"
	"strconv"
	//"golang.org/x/text/number"
	//"testing/quick"
)

//最左边下标left
//右边下标right
type Stack struct{
	MaxTop int //表示我们栈最大可以存放个数
	Top int //表示栈顶
	arr [20]int
}
func (this *Stack)push(val int) (err error){
	// 
	if this.Top==this.MaxTop-1{
		fmt.Printf("栈满")
		return errors.New("栈满溢出")
	}
	this.Top++
	this.arr[this.Top]=val
	return

}
func (this *Stack)Pop() (val int,err error){
	if this.Top==-1{
		fmt.Println("空栈")
		//val = -2
		return -2, errors.New("栈空")
	}
	val = this.arr[this.Top]
	this.Top--
	return val,nil
}
//遍历栈时需要从栈顶开始遍历
func (this *Stack)list(){
	//判断栈是否为空
	if this.Top==-1{
		fmt.Println("是一个空栈")
	}
//	curTop = this.Top
	for i:=this.Top;i>=0;i--{
		fmt.Printf("arr[%d]=%d\n",i,this.arr[i])
	}
}
//判断一个字符是不是运算符
func (this *Stack) IsOper(val int) bool{
	if val ==42||val==43 || val==45|| val==47{
		return true
	}else{
		return false
	}
}
func (this *Stack) Cal(num1 int,num2 int ,oper int) int{
	res :=0
	switch oper{
	case 42:
		res= num2*num1
	case 43:
		res=num2+num1
	case 45:
		res= num2-num1
	case 47:
		res= num2/num1
	default:
		fmt.Println("运算符错误")

	}
	return res
}
//编写一个方法返回某个运算符优先级
func (this *Stack) Priority(oper int) int{
	res := 0
	if oper==42|| oper==47 {
		res= 1
	}else if oper== 43|| oper==45{
		res= 0
	}
	return res


}
func main(){
	//数栈
	numStack := &Stack{
		MaxTop: 20,
		Top: -1,
	}
	operStack := &Stack{
		MaxTop: 20,
		Top: -1,
	}
	exp := "3+3*6-4"
	index := 0
	num1:=0
	num2:=0
	oper:= 0
	result:=0
	for {
		ch := exp[index:index+1]//字符串
		temp := int([]byte(ch)[0])//字符对应aSSIC码值
		if operStack.IsOper(temp) {//说明
			if operStack.Top == -1{
				operStack.push(temp)
			}else{
				if operStack.Priority(operStack.arr[operStack.Top])>=operStack.Priority(temp){
					num1,_=numStack.Pop()
					num2,_=numStack.Pop()
					oper,_=operStack.Pop()
					result= operStack.Cal(num1,num2,oper)
					//结果压入数栈
					numStack.push(result)
					//结果压入符号栈
					operStack.push(temp)

				}else{
					operStack.push(temp)
				}
				
			}
			
		}else{//数字
			val,_ := strconv.ParseInt(ch,10,64)
			numStack.push(int(val))
		}
		//继续扫描;判断index 是否到最后
		if index+1 == len(exp) {
			break
		}
		index++

	}
	for{
		if operStack.Top==-1{
			break
		}
		num1,_=numStack.Pop()
		num2,_=numStack.Pop()
		oper,_=operStack.Pop()
		result= operStack.Cal(num1,num2,oper)
		//结果压入数栈
		numStack.push(result)
		//结果压入符号栈
		//operStack.push(temp)

	}
  // 如果算法正确没有问题,表达式也是正确,则结果就是numStack 最后
  res,_:=numStack.Pop()
  fmt.Printf("表达式%s=%v\n",exp,res)


}

  多位数

package main

import (
	"errors"
	"fmt"
	"strconv"
	//"golang.org/x/text/number"
	//"testing/quick"
)

//最左边下标left
//右边下标right
type Stack struct{
	MaxTop int //表示我们栈最大可以存放个数
	Top int //表示栈顶
	arr [20]int
}
func (this *Stack)push(val int) (err error){
	// 
	if this.Top==this.MaxTop-1{
		fmt.Printf("栈满")
		return errors.New("栈满溢出")
	}
	this.Top++
	this.arr[this.Top]=val
	return

}
func (this *Stack)Pop() (val int,err error){
	if this.Top==-1{
		fmt.Println("空栈")
		//val = -2
		return -2, errors.New("栈空")
	}
	val = this.arr[this.Top]
	this.Top--
	return val,nil
}
//遍历栈时需要从栈顶开始遍历
func (this *Stack)list(){
	//判断栈是否为空
	if this.Top==-1{
		fmt.Println("是一个空栈")
	}
//	curTop = this.Top
	for i:=this.Top;i>=0;i--{
		fmt.Printf("arr[%d]=%d\n",i,this.arr[i])
	}
}
//判断一个字符是不是运算符
func (this *Stack) IsOper(val int) bool{
	if val ==42||val==43 || val==45|| val==47{
		return true
	}else{
		return false
	}
}
func (this *Stack) Cal(num1 int,num2 int ,oper int) int{
	res :=0
	switch oper{
	case 42:
		res= num2*num1
	case 43:
		res=num2+num1
	case 45:
		res= num2-num1
	case 47:
		res= num2/num1
	default:
		fmt.Println("运算符错误")

	}
	return res
}
//编写一个方法返回某个运算符优先级
func (this *Stack) Priority(oper int) int{
	res := 0
	if oper==42|| oper==47 {
		res= 1
	}else if oper== 43|| oper==45{
		res= 0
	}
	return res


}
func main(){
	//数栈
	numStack := &Stack{
		MaxTop: 20,
		Top: -1,
	}
	operStack := &Stack{
		MaxTop: 20,
		Top: -1,
	}
	exp := "30+30*6-4"
	index := 0
	num1:=0
	num2:=0
	oper:= 0
	result:=0
	keepNum := ""
	for {
		//增加一个逻辑;处理
		ch := exp[index:index+1]//字符串
		temp := int([]byte(ch)[0])//字符对应aSSIC码值
		if operStack.IsOper(temp) {//说明
			if operStack.Top == -1{
				operStack.push(temp)
			}else{
				if operStack.Priority(operStack.arr[operStack.Top])>=operStack.Priority(temp){
					num1,_=numStack.Pop()
					num2,_=numStack.Pop()
					oper,_=operStack.Pop()
					result= operStack.Cal(num1,num2,oper)
					//结果压入数栈
					numStack.push(result)
					//结果压入符号栈
					operStack.push(temp)

				}else{
					operStack.push(temp)
				}
				
			}
			
		}else{//数字
			//多位数
			//1.定义一个变量,keepNum string,做拼接
			//2.每次要向后
			//如果到已经到表达最后,直接keepMum
			keepNum += ch
			if index == len(exp)-1{
				val,_ := strconv.ParseInt(keepNum,10,64)
				numStack.push(int(val))

			}else {
				if operStack.IsOper(int([]byte(exp[index+1:index+2])[0])){
					val,_ := strconv.ParseInt(keepNum,10,64)
					numStack.push(int(val))
					//operStack.push(int(val))
					keepNum=""

				}
			}

			// val,_ := strconv.ParseInt(ch,10,64)
			// numStack.push(int(val))
		}
		//继续扫描;判断index 是否到最后
		if index+1 == len(exp) {
			break
		}
		index++

	}
	for{
		if operStack.Top==-1{
			break
		}
		num1,_=numStack.Pop()
		num2,_=numStack.Pop()
		oper,_=operStack.Pop()
		result= operStack.Cal(num1,num2,oper)
		//结果压入数栈
		numStack.push(result)
		//结果压入符号栈
		//operStack.push(temp)

	}
  // 如果算法正确没有问题,表达式也是正确,则结果就是numStack 最后
  res,_:=numStack.Pop()
  fmt.Printf("表达式%s=%v\n",exp,res)


}
// 执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter20\demo12\main.go
// 表达式30+30*6-4=206

  排序方法速度分析

选择

package main

import (
	//"crypto/cipher"
	"math/rand"
	"time"
	//"crypto/rand"
	"fmt"
	//"github.com/redis/go-redis/v9/helper"
)

func SelectSort(arr *[80000]int){
	//arr[1]=600
	for x:=0;x<len(arr)-1;x++{
		max :=arr[x]
		maxIndex :=x
		for i:=x+1;i<len(arr);i++{
			if max < arr[i]{
				max=arr[i]
				maxIndex=i
				// arr[maxIndex]=arr[i]
			}
		}
		if maxIndex != x{
			arr[x],arr[maxIndex] = arr[maxIndex],arr[x]
		}
		//fmt.Printf("第%d次交换结构结果;%d;\n",x,*arr)
	}
}
func main(){
	//arr := [5]int{10,34,19,100,80}
	var arr [80000]int
	for i:=0;i<80000;i++{
		// arr[i]=rand.Intn(9000000)
		arr[i]=rand.Intn(900000)
	}
	start:=time.Now().Unix()
	SelectSort(&arr)
	end:= time.Now().Unix()
	fmt.Printf("耗时=%d秒",end-start)
	//fmt.Println(arr)
}
//执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter20\demo08\main.go
// 耗时=3秒

  插入

package main

import (
	"fmt"
	"math/rand"
	"time"
)
func InsertSort(arr *[80000]int){
	// insertVal:=arr[1]
	// insertIdex:=1-1//下标
	for i :=1;i<len(arr);i++{
		insertVal:=arr[i]
		insertIdex:=i-1//下标
		for insertIdex>=0&& arr[insertIdex]<insertVal{
		// if arr[insertIdex]< insertVal{
		// 	arr[insertIdex]=arr[insertIdex+1]
		// }
			arr[insertIdex+1]=arr[insertIdex]
			insertIdex--
		}
		if insertIdex+1!=insertIdex{
		arr[insertIdex+1]=insertVal
		}
		//fmt.Printf("第%d次,%d\n",i,*arr)
	}
}
func main(){
  //arr:=[5]int{23,0,12,56,34}
  var arr [80000]int
	for i:=0;i<80000;i++{
		// arr[i]=rand.Intn(9000000)
		arr[i]=rand.Intn(900000)
	}
	start:=time.Now().Unix()
  	InsertSort(&arr)
	end:= time.Now().Unix()
	fmt.Printf("耗时=%d秒",end-start)

}
//执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter20\demo09\main.go
// 耗时=2秒

  快速

package main

import (
	"fmt"
	//"testing/quick"
	"math/rand"
	"time"
)
//最左边下标left
//右边下标right
func QuickSort(left int,right int,array *[80000]int){
	l := left
	r := right
	//中轴
	pivot := array[(left+right)/2]
	//temp:=0
	//比pivot 小的数放到左边
	//比pivot 大的数放到右边

	for;l<r;{
		for ; array[l]<pivot;{
			l++
		}
		for ;array[r]>pivot;{
			r--
		}
		//表示
		if l>=r{
			break
		}
		// temp = array[l]
		// array[l]= array[r]
		// array[r]=temp
		array[l],array[r]=array[r],array[l]
		if array[l]==pivot{
			r--
		}
		if array[r]==pivot{
			l++
		}
	}

	if l==r{
		l++
		r--
	}
	//向做
	if left<r{
		QuickSort(left,r,array)
	}
	if right>l{
		QuickSort(l,right,array)
	}


}
func main(){
//   arr:=[6]int{-9,78,0,23,-567,70}
 	var arr [80000]int
	for i:=0;i<80000;i++{
		// arr[i]=rand.Intn(9000000)
		arr[i]=rand.Intn(900000)
	}
	start:=time.Now().Unix()
	QuickSort(0,len(arr)-1,&arr)
	end:= time.Now().Unix()
	fmt.Printf("耗时=%d秒",end-start)
  
}
// 执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter20\demo10\main.go
// 耗时=0秒

  递归

递归概念

简单说递归就是函数/方法自己调自己,每次调用传入不同变量,递归有助于编程者解决复杂的问题,同时让代码简洁

image

 递归原则

1)执行函数时,就创建一个新的受保护的独立栈(新栈函数)

2)函数的局部变量是独立的,不会互相影响;如果希望各个函数栈使用同一个数据,使用引用传递

3)递归必须向退出递归的条件逼近,否则就是无限递归

4)当一个函数执行完毕,或者遇到return,就返回,遵守谁调用,将结果给谁,同时当函数执行完毕或者返回时,该函数本身也会被系统销毁

示例

package main
import "fmt"
func SetWay(mymap *[8][7]int,i int,j int) bool{
	//什么情况找到出路
	//myMap[6][5]==2 ;出口
	if mymap[6][5]==2{ 
		return  true
	}else{
		if mymap[i][j]==0{
			//假设这个点是通的;但实际通不通需要探测
			mymap[i][j]=2
			if SetWay(mymap,i+1,j){//下
				return  true
			}else if SetWay(mymap,i,j+1){//右
				return  true
			}else if SetWay(mymap,i-1,j){//上
				return  true
			}else if SetWay(mymap,i,j-1){//左
				return  true
			}else{
				mymap[i][j]=3
				return false
			}


		}else{
			return false
		}
	}


}
func main(){
	//规则
	//如果元素值为1就表示墙
	//2.元素为0 表示路没有走过
	//3. 如果元素2 值,表示通路
	//4.如果元素的值为3,表示走过的路,走不通

	var mymap [8][7]int
	//先把地图最上和最小设置为墙1
	for i:=0;i<7;i++{
		mymap[0][i]=1
		mymap[7][i]=1
		if mymap[i][0]!=1{ 
			mymap[i][0]=1
		}
		if mymap[i][6]!=1{
			mymap[i][6]=1
		}
		
	}
	mymap[3][1]=1
	mymap[3][2]=1
	// mymap[1][2]=1
	// mymap[2][2]=1
	SetWay(&mymap,1,1)
	fmt.Println("探测完毕")
	for i:=0;i<8;i++{
		for j:=0;j<7;j++{
			fmt.Printf("%d ",mymap[i][j])
		}
		fmt.Println()
	}
	//SetWay(&mymap,1,1)
}
// 执行结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter21\demo02\main.go
// 探测完毕
// 1 1 1 1 1 1 1 
// 1 2 0 0 0 0 1 
// 1 2 2 2 0 0 1 
// 1 1 1 2 0 0 1 
// 1 0 0 2 0 0 1 
// 1 0 0 2 0 0 1 
// 1 0 0 2 2 2 1 
// 1 1 1 1 1 1 1 

  哈希表

散列表(哈希表)是根据关键码值(key value)而直接进来的进行访问的数据结构的,也就是说,它通过关键码值映射到表中一个位置来访问记录,以加快查找的速度,这个映射叫散列函数,存放记录的数组叫做散列表

image

代码实现

PS D:\golang\goproject\src\src01\go_code\src> go run chapter21\demo03\main.go
============选择菜单================
input 添加雇员
show 显示所有雇员
find 查找雇员
exit 退出
输入你的选择:input
输入雇员ID1
输入名字tom
============选择菜单================
input 添加雇员
show 显示所有雇员
find 查找雇员
exit 退出
输入你的选择:show
链表0 为空
链表1雇员id=1名字=tom->
链表2 为空
链表3 为空
链表4 为空
链表5 为空
链表6 为空
============选择菜单================
input 添加雇员
show 显示所有雇员
find 查找雇员
exit 退出
输入你的选择:input
输入雇员ID22
输入名字chenxi
============选择菜单================
input 添加雇员
show 显示所有雇员
find 查找雇员
exit 退出
输入你的选择:show
链表0 为空
链表1雇员id=1名字=tom->链表1雇员id=22名字=chenxi->
链表2 为空
链表3 为空
链表4 为空
链表5 为空
链表6 为空
============选择菜单================
input 添加雇员
show 显示所有雇员
find 查找雇员
exit 退出
输入你的选择:exit

  查找实现

package main

import (
	//"embed"
	"fmt"
	"os"
	//"time"
	//"golang.org/x/text/cases"
)

//定义
type Emp struct{
	Id int 
	Name string
	Next *Emp
}
func (this *Emp)showMe(){
	fmt.Printf("链表%d,找到该雇员%d\n",this.Id % 7,this.Id)
}
//定义EmpLink,
type EmpLink struct{
	Head *Emp
}
func (this *EmpLink)Insert(emp *Emp){
	cur := this.Head
	var pre *Emp =nil
	//如果是空指针
	if cur == nil{
		this.Head=emp
		return
	}
	//如果不是一个空列表,给emp找到对应位置并插入
	//思路让cur 和emp 比较,然后pre保持在cru 前面
	for {
		if cur != nil{
			if cur.Id>=emp.Id{
				//找到位置
				break
			}
			pre =cur//
			cur= cur.Next
		}else{
			break
		}
	}
	// 退出时。将看一下是否将emp添加到链表的最后
	//if cur ==nil{
		pre.Next = emp
		emp.Next= cur
	// }else{
	// 	pre.Next = emp
	// 	emp.Next= cur
	// }
}
//显示当前链表信息
func (this *EmpLink)ShowLink(no int){
	if this.Head ==nil{
		fmt.Printf("链表%d 为空\n",no)
		return
	}
	cur := this.Head
	for{
		if cur !=nil{
			fmt.Printf("链表%d雇员id=%d名字=%s->",no,cur.Id,cur.Name)
			cur= cur.Next
		}else{
			break
		}
	}
	fmt.Println()
}
//根据ID查雇员
func (this *EmpLink) FindById(id int) *Emp{
	cur :=this.Head
	for{
		if cur !=nil&& cur.Id==id{
			return cur
		}else if cur == nil{
			break
		}
		cur = cur.Next
	}
	return nil
}
type HashTable struct{
	Head *Emp
	LinkArr [7]EmpLink

}
//给哈希TAble 编写Insert 雇员的方法。
func(this *HashTable)Insert(emp *Emp){
	linkNo:=this.HashFun(emp.Id)
	//确定将雇员添加哪个列表
	this.LinkArr[linkNo].Insert(emp)

} 
//显示所有雇员
func (this *HashTable)ShowAll(){
	for i:=0;i<len(this.LinkArr);i++{
		this.LinkArr[i].ShowLink(i)
	}
}
//编写用于散列函数
func (this *HashTable)HashFun(id int) int{
	return  id %7

}
//编写一个查找方法
func (this *HashTable)FindById(id int)*Emp{
	linkNo:=this.HashFun(id)
	return  this.LinkArr[linkNo].FindById(id)
}

func main(){
	var hashtable HashTable
	key := ""
	id := 0
	name := ""
	for {
		fmt.Println("============选择菜单================")
		fmt.Println("input 添加雇员")
		fmt.Println("show 显示所有雇员")
		fmt.Println("find 查找雇员")
		fmt.Println("exit 退出")
		fmt.Printf("输入你的选择:")
		fmt.Scanln(&key)
		switch key{
		case "input":
			fmt.Printf("输入雇员ID")
			fmt.Scanln(&id)
			fmt.Printf("输入名字")
			fmt.Scanln(&name)
			emp := &Emp{
				Name: name,
				Id: id,
			}
			hashtable.Insert(emp)

		case "show":
			hashtable.ShowAll()
		case "find":
			fmt.Printf("输入要查找的id号:")
			fmt.Scanln(&id)
			emp:=hashtable.FindById(id)
			if emp  ==nil{
				fmt.Println("用户不存在")
			}else{
				emp.showMe()
			}

		case "exit":
			os.Exit(0)
		default:
			fmt.Println("输入有误")
		}

	}

}
//查找
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter21\demo03\main.go
// ============选择菜单================
// input 添加雇员
// show 显示所有雇员
// find 查找雇员
// exit 退出
// 输入你的选择:input
// 输入雇员ID34
// 输入名字chenxi
// ============选择菜单================
// input 添加雇员
// show 显示所有雇员
// find 查找雇员
// exit 退出
// 输入你的选择:find
// 输入要查找的id号:34
// 链表6,找到该雇员34
// ============选择菜单================
// input 添加雇员
// show 显示所有雇员
// find 查找雇员
// exit 退出
// 输入你的选择:exit

  二叉树

使用前序,中旭和后续对下面的二叉数进行遍历

 前序

package main

import (
	//"embed"
	"fmt"
	//"os"
	//"time"
	//"golang.org/x/text/cases"
)
type Hero struct{
	No int
	Name string
	Left *Hero
	Right *Hero

}
//前序遍历
func PreOrder(node *Hero){
	if node  != nil{
		fmt.Printf("no=%d name=%s\n",node.No,node.Name)
		PreOrder(node.Left)
		PreOrder(node.Right)
	}
}
func main(){
	root:=&Hero{
		No:1,
		Name: "宋江",

	}
	left1:= &Hero{
		No: 2,
		Name: "吴用",

	}
	left4:= &Hero{
		No: 10,
		Name: "吴",

	}
	left5:= &Hero{
		No: 5,
		Name: "用",

	}

	right1:=&Hero{
		No: 3,
		Name: "卢俊义",
	}
	root.Left=left1
	root.Right=right1
	right2:=&Hero{
		No: 4,
		Name: "林冲",
	}
	left1.Left=left4
	left1.Right=left5
	right1.Right=right2
	PreOrder(root)

}
//结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter21\demo04\main.go
// no=1 name=宋江
// no=2 name=吴用
// no=10 name=吴
// no=5 name=用
// no=3 name=卢俊义
// no=4 name=林冲

  中旬

package main

import (
	//"embed"
	"fmt"
	//"os"
	//"time"
	//"golang.org/x/text/cases"
)
type Hero struct{
	No int
	Name string
	Left *Hero
	Right *Hero

}
//前序遍历
func PreOrder(node *Hero){
	if node  != nil{
		fmt.Printf("no=%d name=%s\n",node.No,node.Name)
		PreOrder(node.Left)
		PreOrder(node.Right)
	}
}
//中旬
func InfixOrder(node *Hero){
	if node  != nil{
		
		InfixOrder(node.Left)
		fmt.Printf("no=%d name=%s\n",node.No,node.Name)
		InfixOrder(node.Right)
	}
}
func main(){
	root:=&Hero{
		No:1,
		Name: "宋江",

	}
	left1:= &Hero{
		No: 2,
		Name: "吴用",

	}
	left10:= &Hero{
		No: 10,
		Name: "tom",

	}
	left12:= &Hero{
		No: 12,
		Name: "杰克",

	}

	right1:=&Hero{
		No: 3,
		Name: "卢俊义",
	}
	root.Left=left1
	root.Right=right1
	right2:=&Hero{
		No: 4,
		Name: "林冲",
	}
	left1.Left=left10
	left1.Right=left12
	right1.Right=right2
	//PreOrder(root)
	InfixOrder(root)

}
//结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter21\demo04\main.go
// no=10 name=tom
// no=2 name=吴用
// no=12 name=杰克
// no=1 name=宋江
// no=3 name=卢俊义
// no=4 name=林冲

  后序遍历

package main

import (
	//"embed"
	"fmt"
	//"os"
	//"time"
	//"golang.org/x/text/cases"
)
type Hero struct{
	No int
	Name string
	Left *Hero
	Right *Hero

}
//前序遍历
func PreOrder(node *Hero){
	if node  != nil{
		fmt.Printf("no=%d name=%s\n",node.No,node.Name)
		PreOrder(node.Left)
		PreOrder(node.Right)
	}
}
//中旬
func InfixOrder(node *Hero){
	if node  != nil{
		
		InfixOrder(node.Left)
		fmt.Printf("no=%d name=%s\n",node.No,node.Name)
		InfixOrder(node.Right)
	}
}
func PostOrder(node *Hero){
	if node  != nil{
		
		PostOrder(node.Left)
		
		PostOrder(node.Right)
		fmt.Printf("no=%d name=%s\n",node.No,node.Name)
	}
}
func main(){
	root:=&Hero{
		No:1,
		Name: "宋江",

	}
	left1:= &Hero{
		No: 2,
		Name: "吴用",

	}
	left10:= &Hero{
		No: 10,
		Name: "tom",

	}
	left12:= &Hero{
		No: 12,
		Name: "杰克",

	}

	right1:=&Hero{
		No: 3,
		Name: "卢俊义",
	}
	root.Left=left1
	root.Right=right1
	right2:=&Hero{
		No: 4,
		Name: "林冲",
	}
	left1.Left=left10
	left1.Right=left12
	right1.Right=right2
	//PreOrder(root)
	//InfixOrder(root)
	PostOrder(root)

}
//结果
// PS D:\golang\goproject\src\src01\go_code\src> go run chapter21\demo04\main.go
// no=10 name=tom
// no=12 name=杰克
// no=2 name=吴用
// no=4 name=林冲
// no=3 name=卢俊义
// no=1 name=宋江

  

posted @ 2026-04-23 17:13  烟雨楼台,行云流水  阅读(10)  评论(0)    收藏  举报