通过golang实现一些经典算法问题

1、sparsearray 稀疏数组

1.1、先看一个问题
在这里插入图片描述
1.2、基本介绍
在这里插入图片描述
在这里插入图片描述
1.3、举栗说明
在这里插入图片描述
1.4、应用实例
在这里插入图片描述
在这里插入图片描述
代码:

package main

import "fmt"

/**
 *  @Description:稀疏数组
 *  @Author: guai
 *  @Date:2020/3/1 9:06
**/

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值节点
	valArr := valNode{
		row: 11,
		col: 11,
		val: 0,
	}
	sparseArr = append(sparseArr, valArr)
	for i, v := range chessMap {
		for j, v1 := range v {
			if v1 != 0 {
				valArr := valNode{
					row: i,
					col: j,
					val: v1,
				}
				sparseArr = append(sparseArr, valArr)
			}

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

	//4、将稀疏数组复原
	//创建原始数组
	var chessMap1 [11][11]int
	for i,valArr:=range sparseArr{
		if i!=0{
			chessMap1[valArr.row][valArr.col]=valArr.val
		}
	}

	for _,val:=range chessMap1{
		for _,val1:=range val{
			fmt.Printf("%d \t",val1)
		}
		fmt.Println()
	}
}

结果:
在这里插入图片描述

2、golang中队列的实现
2.1、应用场景
在这里插入图片描述
2.2、队列介绍
在这里插入图片描述
在这里插入图片描述

2.3、数组模拟队列 front前rear后
在这里插入图片描述
2.4、实现一个非环形的队列(数组来实现)
在这里插入图片描述
在这里插入图片描述
代码:

package main

import (
	"errors"
	"fmt"
	"os"
)

/**
*  @Description: golang中队列的实现
 *  @Author: guai
 *  @Date:2020/3/1 9:34
**/
//顶定义一个队列结构体
type queueType struct {
	array   [5]int
	maxSize int
	front   int
	rear    int
}

//添加数据
func (this *queueType) addQueue(val int) (err error) {
	//判断队列满否
	if this.rear == this.maxSize-1 {
		return errors.New("queue is full")
	}
	//rear 后移
	this.rear++
	this.array[this.rear] = val
	return
}

//取出数据
func (this *queueType) getQueue() (val int, err error) {
	//判断队列空否
	if this.rear == this.front {
		return 0, errors.New("queue is empty")
	}
	this.front++
	return this.array[this.front], nil
}

//显示队列
func (this *queueType) showQueue() (err error) {
	if this.rear == this.front {
		return errors.New("queue is empty")
	}
	for i := this.front + 1; i <= this.rear; i++ {
		fmt.Printf("array[%d]:%d\n", i, this.array[i])
	}
	return nil
}
func main() {
	queueT := &queueType{
		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("1、输入exit退出程序")

		fmt.Scan(&key)
		switch key {
		case "add":
			fmt.Println("请输入一个整数")
			fmt.Scan(&val)
			err := queueT.addQueue(val)
			if err != nil {
				fmt.Println("add err:", err.Error())
			} else {
				fmt.Println("add success")
			}
		case "get":
			val, err := queueT.getQueue()
			if err != nil {
				fmt.Println("get err:", err.Error())
			} else {
				fmt.Println("get val:", val)
			}
		case "show":
			err := queueT.showQueue()
			if err != nil {
				fmt.Println("show err:", err.Error())
			}
		case "exit":
			fmt.Println("exit")
			os.Exit(0)
		default:
			fmt.Println("input err,input again please!")
		}
	}
}

结果:
在这里插入图片描述
2.5、实现一个循环队列 (通过数据完成)
在这里插入图片描述

package main

import (
	"errors"
	"fmt"
	"os"
)

/**
 *  @Description: 通过数组实现循环队列  ( ctrl+r:查找替换)
 *  @Author: guai
 *  @Date:2020/3/1 10:26
**/

//定义一个循环队列
type circleQueue struct {
	array [5]int
	//最大值为4
	maxSize int
	//队列头
	head int
	//队列尾
	tail int
}

//判断队列满否
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) push(val int) (err error) {
	//判断队列满否
	if this.isFull() {
		return errors.New("queue is full")
	}

	//分析this。tail在队尾但是包含最后的元素
	this.array[this.tail] = val
	// 当tail==4时 队尾重新回到 0的位置形成circle
	this.tail = (this.tail + 1) % this.maxSize
	return
}

//取出数据
func (this *circleQueue) pop() (val int, err error) {
	//判断队列空否
	if this.isEmpty() {
		return 0, errors.New("queue is empty")
	}
	//取出队列的值
	val = this.array[this.head]
	this.head = (this.head + 1) % this.maxSize
	return

}

//显示队列
func (this *circleQueue) show() (err error) {
	if this.isEmpty() {
		return errors.New("queue is empty")
	}
	tempHead := this.head
	for {
		if tempHead == this.tail {
			return
		}
		fmt.Printf("array[%d]:%d\n", tempHead, this.array[tempHead])
		tempHead = (tempHead + 1) % this.maxSize

	}
	return
}

//返回队列中元素个数
func (this *circleQueue) size() int {
	//这里可能 难理解 注意一点
	return (this.tail + this.maxSize - this.head) % this.maxSize
}
func main() {
	circleQ := &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、输入size显示队列中的元素个数")
		fmt.Println("5、输入exit退出程序")

		fmt.Scan(&key)
		switch key {
		case "add":
			fmt.Println("请输入一个整数")
			fmt.Scan(&val)
			err := circleQ.push(val)
			if err != nil {
				fmt.Println("add err:", err.Error())
			} else {
				fmt.Println("add success")
			}
		case "get":
			val, err := circleQ.pop()
			if err != nil {
				fmt.Println("get err:", err.Error())
			} else {
				fmt.Println("get val:", val)
			}
		case "show":
			err := circleQ.show()
			if err != nil {
				fmt.Println("show err:", err.Error())
			}
		case "size":
			fmt.Println("size:", circleQ.size())
		case "exit":
			fmt.Println("exit")
			os.Exit(0)
		default:
			fmt.Println("input err,input again please!")
		}
	}
}

3、链表

3.1、链表是有序的列表,但它在内存中的存储不连续且无序,如下:

3.2、单链表示意图
链表:
通过节点中的next将多个节点连接起来 形成链表
在这里插入图片描述
3.3、单链表的应用案例

 package main

import (
	"fmt"
)

/**
 *  @Description:链表
 *  @Author: guai
 *  @Date:2020/3/1 12:20
**/
//定义节点类型
type vegetablesNode struct {
	name  string
	age   int
	skill string
	next  *vegetablesNode
}
//在末尾添加节点
func (list *vegetablesNode) add(newNode *vegetablesNode) {
	defer func() {
		err := recover()
		if err != nil {
			fmt.Println("err:", err)
		}
	}()
	//中间节点
	tempNode := list
	for {
		if tempNode.next == nil {
			break
		}
		tempNode = tempNode.next
	}
	tempNode.next = newNode

}
//显示所有节点
func (list *vegetablesNode) show() {
	tempNode := list
	for {
		if tempNode == nil {
			break
		}
		fmt.Println("node:", tempNode)
		tempNode = tempNode.next

	}
}
//在指定节点后添加节点
func (list *vegetablesNode) insertNode(name string,newNode *vegetablesNode){
	tempNode:=list
	for{
	    tempNode1:=tempNode.next

	    if tempNode==nil{
			fmt.Println("no found :",name)
			break
		}
		if tempNode.name==name{
			newNode.next=tempNode1
			tempNode.next=newNode
			fmt.Println("insert success")
			break
		}
	}
}

func main() {
	list:=vegetablesNode{
		name:"cabbage",
		age:12,
		skill:"eat",
	}

	list.add(&vegetablesNode{
		name:"radish",
		age:12,
		skill:"eat",
	})
	list.show()
	list.insertNode("cabbage",&vegetablesNode{
		name:"chives",
		age:12,
		skill:"eat",
	})
	list.show()
}

结果:
在这里插入图片描述

3.4、双向链表
每个节点中有指向前一个节点的 pre和指向后一个结点的next 形成双向的链表
在这里插入图片描述

package main

import "fmt"

/**
 *  @Description:双向链表
 *  @Author: guai
 *  @Date:2020/3/1 13:17
**/

//定义节点类型
type doublyLinkedNode struct {
	name  string
	age   int
	skill string
	pre   *doublyLinkedNode
	next  *doublyLinkedNode
}

//在末尾添加节点
func (list *doublyLinkedNode) add(newNode *doublyLinkedNode) {
	defer func() {
		err := recover()
		if err != nil {
			fmt.Println("err:", err)
		}
	}()
	//中间节点
	tempNode := list
	for {
		if tempNode.next == nil {
			break
		}
		tempNode = tempNode.next
	}
	newNode.pre=tempNode
	tempNode.next = newNode
}

//显示所有节点
func (list *doublyLinkedNode) show() {
	tempNode := list
	for {
		if tempNode == nil {
			break
		}
		fmt.Println("node:", tempNode)
		tempNode = tempNode.next

	}
}

//在指定节点后添加节点
func (list *doublyLinkedNode) insertNode(name string, newNode *doublyLinkedNode) {
	tempNode := list
	for {
		tempNode1 := tempNode.next

		if tempNode == nil {
			fmt.Println("no found :", name)
			break
		}
		if tempNode.name == name {

			newNode.next = tempNode1
			tempNode1.pre=newNode

			tempNode.next = newNode
			newNode.pre=tempNode
			fmt.Println("insert success")
			break
		}
	}
}

func main() {
	list := doublyLinkedNode{
		name:  "cabbage",
		age:   12,
		skill: "eat",
	}

	list.add(&doublyLinkedNode{
		name:  "radish",
		age:   12,
		skill: "eat",
	})
	list.show()
	list.insertNode("cabbage", &doublyLinkedNode{
		name:  "chives",
		age:   12,
		skill: "eat",
	})
	list.show()
}

结果:
在这里插入图片描述

3.5、循环链表
在这里插入图片描述
循环链表介绍
在这里插入图片描述
循环列表练习:

package main

import (
	"fmt"
)

/**
 *  @Description:循环列表
 *  @Author: guai
 *  @Date:2020/3/1 12:20
**/

//定义节点类型
type circleNode struct {
	name  string
	age   int
	skill string
	next  *circleNode
}

//在末尾添加节点
func (list *circleNode) add(newNode *circleNode) {
	defer func() {
		err := recover()
		if err != nil {
			fmt.Println("err:", err)
		}
	}()

	//中间节点
	tempNode := list
	for {
		if tempNode.next == list {
			break
		}
		tempNode = tempNode.next
	}
	newNode.next = list
	tempNode.next = newNode

}

//显示所有节点
func (list *circleNode) show() {
	tempNode := list
	for {
		fmt.Println("node:", tempNode, list)

		if tempNode.next == list {
			break
		}
		tempNode = tempNode.next
	}
}

//删除节点
func (list *circleNode) del(name string) {

	if list == nil {
		fmt.Println("list is empty")
		return
	}
	tempNode := list
	//当只有一个节点时
	if tempNode.next == list {
		if tempNode.name == name {
			tempNode = nil
			fmt.Println("del success")
			return
		}
	}
	//将endNode定位到链表最后
	endNode := list
	for {
		if endNode.next == list {
			break
		}
		endNode = endNode.next
	}
	fmt.Println("flagq")

	for {
		if tempNode.next == list {
			break
		}

		if tempNode.name == name {
			//删除的是头节点
			if tempNode == list {
				 *list = *list.next
			//	list.show()
				endNode.next=list
				fmt.Println("del success")
				return
			} else {
				  *endNode.next= *tempNode.next
				fmt.Println("del success1")
				return
			}
		}
		endNode = endNode.next
		tempNode = tempNode.next
	}

	fmt.Println("del fail case by name not found")
}

//在指定节点后添加节点
func (list *circleNode) insertNode(name string, newNode *circleNode) {
	tempNode := list
	if tempNode == nil {
		fmt.Println("no found :", name)
		return
	}
	for {
		tempNode1 := tempNode.next
		if tempNode.name == name {
			newNode.next = tempNode1
			tempNode.next = newNode
			fmt.Println("insert success")
			return
		}
		if tempNode.next == list {
			fmt.Println("no found ",name)
			return
		}
		tempNode=tempNode.next
	}
}

func main() {
	list := circleNode{
		name:  "cabbage",
		age:   12,
		skill: "eat",
	}
	list.next = &list

	list.add(&circleNode{
		name:  "radish",
		age:   12,
		skill: "eat",
	})
	//list.show()
	list.add(&circleNode{
		name:  "radish1",
		age:   12,
		skill: "eat",
	})

	list.show()
	list.insertNode("cabbage", &circleNode{
		name:  "chives",
		age:   12,
		skill: "eat",
	})
	list.show()

	//list.del("cabbage")
	//fmt.Println(list)
	//list.show()

	list.del("radish")
	fmt.Println(list)
	list.show()
}

结果:
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值