环形链表的一种Go语言实现
package mainimport "fmt"//定义一个环形链表的节点构造体type circleSingleLink struct { id int name string next *circleSingleLink}//插入节点到环形链表func Insert(head, newnode *circleSingleLink) { //判断是否为空链表 if head.next == nil{ //如果为空则把增加的第一个元素给头节点,这里和其余链表有些区别,其余链表头结点是空的 head.id = newnode.id head.name = newnode.name //重点是要让一个节点也造成一个环形,即收尾相接 head.next = head return } //增加非头结点到环形链表 temp := head for{ if temp.next == head { //尾部增加 temp.next = newnode newnode.next = head break } temp = temp.next }}//显示环形链表的所有节点信息func CircleList(head *circleSingleLink){ //判断链表是否为空 if head.next == nil { fmt.Println("链表为空") return } temp := head for { fmt.Printf("[%d %s] -> ", temp.id, temp.name) //留神这里是这样判断终止条件的 if temp.next == head{ break } temp = temp.next }}//删除环形链表的一个节点(难点)func CircleDelete(head, node *circleSingleLink) *circleSingleLink { //之所以有返回值是因为头结点的值和指向要发生变化 //删除思路: //先让temp 指向head //再让helper指向环形链表的最初 //让temp和要删除的节点比拟,如果雷同,则让helper实现删除节点,重点是要思考是否为头结点,因为环形链表的头结点有值 temp := head if temp.next == nil { //链表为空的时候 fmt.Println("链表为空") return head } if temp.next == head { //只有一个头结点的环形链表 temp.next = nil return head } helper := head for { if helper.next == head { break } helper = helper.next //将指针定位到环形链表的尾节点 } //如果有两个及以上的节点 for { if temp.next == head { //阐明到最初一个并且还没判断是否是要删除的节点 if temp.id == node.id { helper.next = temp.next }else { fmt.Println("没有该节点") } break } if temp.id == node.id { //找到了要删除的节点 if temp == head { //如果删除的是头结点 head = head.next } //删除非头结点 helper.next = temp.next //helper始终在temp的后一个 break } temp = temp.next //用作比拟 helper = helper.next //用作操作 } return head}func main(){ //定义一个链表的头 head := &circleSingleLink{} //定义第一个节点 node1 := &circleSingleLink{ id: 1, name : "number1", } node2 := &circleSingleLink{ id: 2, name : "number2", } node3 := &circleSingleLink{ id: 3, name : "number3", } Insert(head, node1) Insert(head, node2) Insert(head, node3) head = CircleDelete(head, node1) CircleList(head)}
约瑟夫问题:
package mainimport "fmt"type Boy struct { id int next *Boy}//创立一个环形链表,并返回头指针func CreateLink(num int) *Boy { first := &Boy{} //头指针不能动,因而须要一个辅助指针进行循环创立 curBoy := &Boy{} if num < 1 { return first } for i := 1; i <= num; i++ { boy := &Boy{ id: i, next: nil, } if i == 1 { //因为第一个小孩比拟非凡 first = boy curBoy = boy curBoy.next = first }else { curBoy.next = boy curBoy = boy curBoy.next = first //形成环形链表 } } return first}//显示环形链表func ShowBoy (first *Boy) { if first.next == nil { fmt.Println("链表为空") return } curBoy := first for { fmt.Printf("小孩%d -> ", curBoy.id) if curBoy.next == first { break } curBoy = curBoy.next }}//应用环形链表实现约瑟夫问题func PlayGame(first *Boy, startNo int, countNum int) { //空链表的状况 if first.next == nil { fmt.Println("链表为空,游戏完结") return } //定义两个指针循环,其中first负责比拟,tail负责删除 tail := first //将tail斧正定位到链表的最初 for { if tail.next == first { break } tail = tail.next } //开始挪动startNo-1步 for i := 0; i < startNo -1; i++ { first = first.next tail = tail.next } fmt.Println() //开始循环删除环形链表中第countNum-1个节点 for { for i := 0; i < countNum - 1; i++ { first = first.next tail = tail.next } //打印行将出圈的节点信息 fmt.Printf("编号为%d的节点出圈\n", first.id) //删除此时first指向的以后节点 first = first.next tail.next = first //确定完结条件 if tail == first { break } } //打印最初一个出圈的节点 fmt.Printf("编号为%d的节点出圈\n", first.id)}func main(){ first := CreateLink(51) ShowBoy(first) PlayGame(first, 2, 3)}