Go双向链表

文章目录

楔子

go 学习

demo

package main

import (
	"fmt"
)

//双链表|
type HeroNode struct {
	no       int
	name     string
	nickname string
	next     *HeroNode //下一个英雄
	pre      *HeroNode
}

func (h *HeroNode) String() string {
	return fmt.Sprintf("[%d %s %s]==>", h.no, h.name, h.nickname)
}
func InsertHeroNode(head *HeroNode, newHeroNode *HeroNode) {
	//思路
	//1. 先找到该链表的最后这个结点
	temp := head
	for {
		if temp.next == nil { //表示找到最后
			break
		}
		temp = temp.next // 让temp不断的指向下一个结点
	}

	//3. 将newHeroNode加入到链表的最后
	temp.next = newHeroNode
	newHeroNode.pre = temp
}

//显示链表的所有结点信息
func ListHeroNode(head *HeroNode) {
	//1. 创建一个辅助结点[跑龙套, 帮忙]
	temp := head
	// 先判断该链表是不是一个空的链表
	if temp.next == nil {
		fmt.Println("空空如也。。。。")
		return
	}
	//2. 遍历这个链表
	for {
		fmt.Printf("[%d , %s , %s]==>", temp.next.no,
			temp.next.name, temp.next.nickname)
		//判断是否链表后
		temp = temp.next
		if temp.next == nil {
			break
		}
	}
}

func ListHeroNode_my(head *HeroNode) {
	fmt.Println()
	//1 创建临时结点
	temp := head
	//选判断该链表是不是空链表
	for {
		if temp.next == nil {
			break
		}
		temp = temp.next
		fmt.Print(temp)
	}
}
func main() {
	//一个头结点
	head := &HeroNode{}

	//	创建一个新的 heronode
	hero1 := &HeroNode{
		no:       1,
		name:     "宋江",
		nickname: "及时雨",
	}
	hero2 := &HeroNode{
		no:       2,
		name:     "卢俊义",
		nickname: "玉麒麟",
	}

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

	hero5 := &HeroNode{no: 5, name: "关胜", nickname: "大刀",}
	hero7 := &HeroNode{no: 7, name: "林冲", nickname: "豹子头",}

	hero6 := &HeroNode{no: 6, name: "林冲A", nickname: "豹子头A",}
	InsertHeroNode2(head, hero7)
	InsertHeroNode2(head, hero5)

	InsertHeroNode2(head, hero6)

	InsertHeroNode2(head, hero2)
	InsertHeroNode2(head, hero3)
	InsertHeroNode2(head, hero1)

	ListHeroNode_my(head)
	DelHernNode(head, 3)

	ListHeroNode_my(head)

}
func DelHernNode(head *HeroNode, delId int) {
	temp := head
	//TODO 找到要删除的节点
	flag := false
	for {
		if temp.next == nil { //插入到最后
			break
		} else if temp.next.no == delId { //此位置调整之后即可为从大到小
			//找到删除的节点
			flag = true
			break
		}
		temp = temp.next
	}
	if flag {
		if temp.next.next == nil { //该节点就是最后一个节点
			temp.next = nil
		} else {
			temp = temp.next
			temp.pre.next = temp.next
			temp.next.pre = temp.pre
		}
	}
}

//韩顺平 方法
func InsertHeroNode2(head *HeroNode, newHeroNode *HeroNode) {
	//思路
	//1. 先找到该链表的最后这个结点
	//2. 创建一个辅助结点[跑龙套, 帮忙]
	temp := head
	//flag := true
	//	让插入的节点no 和temp的下一个节点no比较
	for ; ; {
		if temp.next == nil { //插入到最后
			break
		} else if temp.next.no >= newHeroNode.no { //此位置调整之后即可为从大到小
			//应该插入temp
			break
		} else if temp.next.no == newHeroNode.no {
			break
		}
		temp = temp.next
	}
	newHeroNode.next = temp.next
	newHeroNode.pre = temp

	if temp.next != nil {
		temp.next.pre = newHeroNode
	}
	//别忘了该节点
	temp.next = newHeroNode

}

约瑟夫

package main

import "fmt"

//编写一个函数,构成单向的环形链表|
type Boy struct {
	No   int
	Next *Boy //指向下一个小孩的指针
}

func (b *Boy) String() string {
	return fmt.Sprintf("[%d ]=>", b.No)
}

// num 小孩个数,
//返回第一个小孩指针
func AddBoy(num int) *Boy {
	first := &Boy{}
	curBoy := &Boy{}
	if num < 1 {
		fmt.Println("num值不对")
		return first
	}
	//构建环形链表
	for i := 1; i <= num; i++ {
		boy := &Boy{
			No: i,
		}

		//1 第一个小孩,|构成循环链表需要一个辅助指针
		if i == 1 {
			first = boy
			curBoy = boy
			curBoy.Next = boy
		} else {
			curBoy.Next = boy
			curBoy = boy
			curBoy.Next = first //构成环形链表
		}
	}

	return first
}

//显示单向环形链表
func showBoy(first *Boy) {
	//如果为空
	if first.Next == nil {
		fmt.Println("链表为空~")
		return
	}

	temp := first //说明至少有1个小孩
	for ; ; {
		fmt.Print(temp)
		if temp.Next == first {
			break
		}
		temp = temp.Next
	}

}

//上面两个方法是环形链表的构建显示
func main() {
	boy := AddBoy(5)
	showBoy(boy)

	fmt.Println()
	PlayGame(boy,2,3)
}

//编号从1 ...n的人围坐一圈,约定编号为k (1<=k<=n)

func PlayGame(first *Boy, startNo int, coutNum int) {
	//1 空链表,单独处理
	if first.Next == nil {
		fmt.Println("空的链表,没有小孩")
		return
	}
	//	startNo要小于小孩的总数
	// 删除小孩
	tail := first //tail执行环形链表的最后一个小孩,
	for {
		if tail.Next == first {
			break
		}
		tail = tail.Next
	}

	for i := 1; i <= startNo-1; i++ {
		first = first.Next
		tail = tail.Next
	}
	//	开始数countNum,删除first指向的小孩
	for {
		for i := 1; i <= coutNum-1; i++ {
			first = first.Next
			tail = tail.Next
		}
		//删除first的节点
		fmt.Println("出列的是", first)
		first = first.Next
		tail.Next = first
		if tail == first {
			break
		}
	}
	fmt.Println("最后的小孩是", first)
}

发布了308 篇原创文章 · 获赞 70 · 访问量 38万+

猜你喜欢

转载自blog.csdn.net/u012848709/article/details/104287069