-
单向链表
1 package main 2 3 import ( 4 "fmt" 5 "os" 6 ) 7 8 //HeroNode 英雄结构体 9 type HeroNode struct { 10 Nom int 11 Name string 12 NickName string 13 Next *HeroNode 14 } 15 16 //InsertHeroNode 插入英雄结点 方法1 简单,但是不好用 17 func InsertHeroNode(head *HeroNode, NewHeroNode *HeroNode) { 18 19 /*创建临时变量t = 头部结点*/ 20 t := head 21 for { 22 /* 如果 临时变量t的下一个是nil,就表示到达的末尾,跳过 */ 23 if t.Next == nil { 24 break 25 } 26 /* 将t的下一个结点给t,那么t会一直判断是否为nil,这样就更加确定,t就代表最后一个结点 */ 27 t = t.Next 28 } 29 /* 添加下一个结点 */ 30 t.Next = NewHeroNode 31 32 } 33 34 //InsertHeroNode2 插入英雄结点方法2 (根据编号大小排序插入数据) 35 func InsertHeroNode2(head *HeroNode, NewHeroNode *HeroNode) { 36 37 /*创建临时变量t = 头部结点*/ 38 t := head 39 flag := true 40 for { 41 if t.Next == nil { 42 break 43 } else if t.Next.Nom > NewHeroNode.Nom { 44 /* > 表示按照从小到大 < 表示 从大到小 >= <= 可根据需求更改*/ 45 break 46 } else if t.Next.Nom == NewHeroNode.Nom { 47 flag = false 48 break 49 } 50 t = t.Next 51 } 52 53 /* 如果flag == true 表示可以存放 */ 54 if flag { 55 56 /* 57 顺序一定先将 新节点的下一个节点指向 → 头部的下一个节点, 58 然后,再将头部的下一个节点指向 → 新节点, 59 不然链表数据就断掉了 60 */ 61 62 /* ,将新节点的下一个结点指向 头部的下一个结点*/ 63 NewHeroNode.Next = t.Next 64 65 /* 将新节点 指向 头部下一个结点 */ 66 t.Next = NewHeroNode 67 68 fmt.Printf("添加节点 %v %v %v 成功 ", NewHeroNode.Nom, NewHeroNode.Name, NewHeroNode.NickName) 69 70 /* 如果 flag == false 不能存放*/ 71 } else { 72 fmt.Printf("添加失败,结点编号 %v 已存在! ", NewHeroNode.Nom) 73 } 74 75 } 76 77 //DelHeroNodeByID 根据ID删除节点 78 func DelHeroNodeByID(head *HeroNode, id int) { 79 t := head 80 state := false 81 for { 82 if t.Next == nil { 83 break 84 } else if t.Next.Nom == id { 85 /* 找到了ID */ 86 state = true 87 break 88 } 89 90 /* 一直往后找 */ 91 t = t.Next 92 } 93 94 if state { 95 /* 96 找到了 删除, 97 将头部的下一个节点 指向 头部的下一个的下一个节点, 98 这样 头部的下一个节点就成垃圾了 99 100 */ 101 t.Next = t.Next.Next 102 fmt.Printf("节点 %v 已删除! ", id) 103 } else { 104 /* 未找到 */ 105 fmt.Printf("您输入的ID号 %v 未找到! ", id) 106 } 107 } 108 109 //UpdateToNode 修改节点信息 110 func UpdateToNode(head *HeroNode, id int, NewHeroNode *HeroNode) { 111 112 /*创建临时变量t = 头部结点*/ 113 t := head 114 flag := false 115 116 for { 117 if t.Next == nil { 118 break 119 } else if t.Next.Nom == id { 120 flag = true 121 break 122 } 123 t = t.Next 124 } 125 fmt.Println("修改节点前", t.Next) 126 /* 如果flag == true 表示可以 修改 */ 127 if flag { 128 t.Next.Nom = NewHeroNode.Nom 129 t.Next.Name = NewHeroNode.Name 130 t.Next.NickName = NewHeroNode.NickName 131 fmt.Println("修改节点成功") 132 fmt.Println("修改节点后", NewHeroNode) 133 /* 如果 flag == false 不能存放*/ 134 } else { 135 fmt.Printf("添加失败,结点编号 %v 已存在! ", NewHeroNode.Nom) 136 } 137 138 } 139 140 //PrintListHeroInfo 输出链表hero信息 141 func PrintListHeroInfo(head *HeroNode) { 142 143 /*创建临时变量t = 头部结点*/ 144 t := head 145 146 /* 判断是否为空 */ 147 if t.Next == nil { 148 fmt.Println("链表为空...") 149 return 150 } 151 152 /* 不为空时执行 */ 153 fmt.Println("链表数据:↓") 154 for { 155 156 fmt.Printf("%v %v %v ", t.Next.Nom, t.Next.Name, t.Next.NickName) 157 158 t = t.Next 159 160 if t.Next == nil { 161 break 162 } 163 164 } 165 fmt.Println() 166 } 167 168 //CRUDToList 增删改查列表 169 func CRUDToList(head *HeroNode) { 170 171 for { 172 var key int 173 var id int 174 var name string 175 var nickeame string 176 var NewNode *HeroNode 177 fmt.Println(" 用户信息链表操作系统") 178 fmt.Println( 179 ` 180 1. 添加节点 181 2. 删除节点 182 3. 修改节点 183 4. 查看链表 184 5. 退出系统 185 请输入(1-5)进行操作 186 `) 187 fmt.Scanln(&key) 188 switch key { 189 case 1: 190 191 fmt.Println("请输入新节点的 [ ID 英雄名称 英雄昵称 ], 以空格分隔输入!") 192 fmt.Scanf("%v %v %v ", &id, &name, &nickeame) 193 NewNode = &HeroNode{ 194 Nom: id, 195 Name: name, 196 NickName: nickeame, 197 } 198 199 InsertHeroNode2(head, NewNode) 200 201 case 2: 202 fmt.Println("请输入删除节点ID") 203 fmt.Scanln(&id) 204 DelHeroNodeByID(head, id) 205 case 3: 206 fmt.Println( 207 ` 208 请输入修改内容 [ id name nickname ] 以空格分隔输入 209 `) 210 fmt.Scanf("%v %v %v ", &id, &name, &nickeame) 211 NewNode = &HeroNode{ 212 Nom: id, 213 Name: name, 214 NickName: nickeame, 215 } 216 UpdateToNode(head, id, NewNode) 217 case 4: 218 PrintListHeroInfo(head) 219 case 5: 220 fmt.Println("已退出系统...") 221 os.Exit(0) 222 default: 223 fmt.Println("操作有误,请输入(1-4)数字!") 224 } 225 } 226 } 227 228 func main() { 229 230 //Hero 链表 头结点HeroListLinkHead 231 head := &HeroNode{} 232 233 CRUDToList(head) 234 }
-
双向链表
1 package main 2 3 import ( 4 "fmt" 5 "os" 6 ) 7 8 /* 9 HeroNode 英雄结构体 10 11 Nom 编号 12 13 Name 名称 14 15 NickName 昵称 16 17 Next 指向下一个节点 18 19 Last 指向上一个节点 20 21 */ 22 type HeroNode struct { 23 Nom int 24 Name string 25 NickName string 26 Next *HeroNode 27 Last *HeroNode 28 } 29 30 //InsertHeroNode 双向链表插入新节点 (根据编号大小排序插入数据) 31 func InsertHeroNode(head *HeroNode, NewHeroNode *HeroNode) { 32 33 /*创建临时变量t = 头部结点*/ 34 t := head 35 flag := true 36 for { 37 if t.Next == nil { 38 break 39 } else if t.Next.Nom > NewHeroNode.Nom { 40 /* > 表示按照从小到大 < 表示 从大到小 >= <= 可根据需求更改*/ 41 break 42 } else if t.Next.Nom == NewHeroNode.Nom { 43 flag = false 44 break 45 } 46 t = t.Next 47 } 48 49 /* 如果flag == true 表示可以存放 */ 50 if flag { 51 52 /* 将 新节点的下一个节点指向 头部节点原先指向的 下一个结点*/ 53 NewHeroNode.Next = t.Next 54 55 /* 将 新节点的上一个节点 指向 t头部节点 */ 56 NewHeroNode.Last = t 57 58 /* 将 头节点的下一个节点的上一个节点不为空时才指向新节点,不然会发生空指针引用 */ 59 if t.Next.Last != nil { 60 /* 将头节点原先指向的下一个节点的上一个节点 指向 新节点 */ 61 t.Next.Last = NewHeroNode 62 } 63 64 /* 将 头部节点的下一个节点 指向 新节点 */ 65 t.Next = NewHeroNode 66 67 fmt.Printf("添加节点 %v %v %v 成功 ", NewHeroNode.Nom, NewHeroNode.Name, NewHeroNode.NickName) 68 69 /* 如果 flag == false 不能存放*/ 70 } else { 71 fmt.Printf("添加失败,结点编号 %v 已存在! ", NewHeroNode.Nom) 72 } 73 74 } 75 76 //DelHeroNodeByID 根据ID删除节点 77 func DelHeroNodeByID(head *HeroNode, id int) { 78 t := head 79 state := false 80 for { 81 if t.Next == nil { 82 break 83 } else if t.Next.Nom == id { 84 /* 找到了ID */ 85 state = true 86 break 87 } 88 89 /* 一直往后找 */ 90 t = t.Next 91 } 92 93 if state { 94 /* 95 找到了 删除, 96 将头部的下一个节点 指向 头部的下一个的下一个节点, 97 这样 头部的下一个节点就成垃圾了 98 99 */ 100 t.Next = t.Next.Next 101 if t.Next != nil { 102 t.Next.Last = t 103 fmt.Printf("节点 %v 已删除! ", id) 104 } 105 106 } else { 107 /* 未找到 */ 108 fmt.Printf("您输入的ID号 %v 未找到! ", id) 109 } 110 } 111 112 //UpdateToNode 修改节点信息 113 func UpdateToNode(head *HeroNode, id int, NewHeroNode *HeroNode) { 114 115 /*创建临时变量t = 头部结点*/ 116 t := head 117 flag := false 118 119 for { 120 if t.Next == nil { 121 break 122 } else if t.Next.Nom == id { 123 flag = true 124 break 125 } 126 t = t.Next 127 } 128 fmt.Println("修改节点前", t.Next) 129 /* 如果flag == true 表示可以 修改 */ 130 if flag { 131 t.Next.Nom = NewHeroNode.Nom 132 t.Next.Name = NewHeroNode.Name 133 t.Next.NickName = NewHeroNode.NickName 134 135 fmt.Println("修改节点成功") 136 fmt.Println("修改节点后", NewHeroNode) 137 138 /* 如果 flag == false 不能存放*/ 139 } else { 140 fmt.Printf("添加失败,结点编号 %v 已存在! ", NewHeroNode.Nom) 141 } 142 143 } 144 145 //PrintListHeroInfo 正向输出链表hero信息 146 func PrintListHeroInfo(head *HeroNode) { 147 148 /*创建临时变量t = 头部结点*/ 149 t := head 150 151 /* 判断是否为空 */ 152 if t.Next == nil { 153 fmt.Println("链表为空...") 154 return 155 } 156 157 /* 不为空时执行 */ 158 fmt.Println("链表数据:↓") 159 for { 160 161 fmt.Printf("%v %v %v ", t.Next.Nom, t.Next.Name, t.Next.NickName) 162 163 t = t.Next 164 165 if t.Next == nil { 166 break 167 } 168 169 } 170 fmt.Println() 171 } 172 173 //PrintListHeroInfoByReverse 你想输出链表信息 174 func PrintListHeroInfoByReverse(head *HeroNode) { 175 t := head 176 if t.Next == nil { 177 fmt.Println("空链表...") 178 return 179 } 180 /* 让t 定位到链表末尾 */ 181 for { 182 if t.Next == nil { 183 break 184 } 185 t = t.Next 186 } 187 188 /* 反向遍历 */ 189 for { 190 fmt.Printf("%v %v %v ", t.Nom, t.Name, t.NickName) 191 t = t.Last 192 if t.Last == nil { 193 break 194 } 195 } 196 } 197 198 //CRUDToList 增删改查列表 199 func CRUDToList(head *HeroNode) { 200 201 for { 202 var key int 203 var id int 204 var name string 205 var nickeame string 206 var NewNode *HeroNode 207 fmt.Println(" 用户信息链表操作系统") 208 fmt.Println( 209 ` 210 1. 添加节点 211 2. 删除节点 212 3. 修改节点 213 4. 查看链表 214 5. 退出系统 215 请输入(1-5)进行操作 216 `) 217 fmt.Scanln(&key) 218 switch key { 219 case 1: 220 221 fmt.Println("请输入新节点的 [ ID 英雄名称 英雄昵称 ], 以空格分隔输入!") 222 fmt.Scanf("%v %v %v ", &id, &name, &nickeame) 223 /* 限制输入 id不能为0 名称不能为空 昵称不能为空,否则不添加 */ 224 225 if name != " " && nickeame != " " { 226 if id == 0 { 227 break 228 } 229 NewNode = &HeroNode{ 230 Nom: id, 231 Name: name, 232 NickName: nickeame, 233 } 234 235 InsertHeroNode(head, NewNode) 236 fmt.Println("节点添加成功") 237 } else { 238 fmt.Println("节点添加失败...") 239 } 240 241 case 2: 242 fmt.Println("请输入删除节点ID") 243 fmt.Scanln(&id) 244 DelHeroNodeByID(head, id) 245 case 3: 246 fmt.Println( 247 ` 248 请输入修改内容 [ id name nickname ] 以空格分隔输入 249 `) 250 fmt.Scanf("%v %v %v ", &id, &name, &nickeame) 251 NewNode = &HeroNode{ 252 Nom: id, 253 Name: name, 254 NickName: nickeame, 255 } 256 UpdateToNode(head, id, NewNode) 257 case 4: 258 fmt.Println( 259 ` 260 请问要看 哪个方向的输出格式的链表? 261 1. 正向输出 262 2. 逆向输出`) 263 fmt.Scanln(&key) 264 switch key { 265 case 1: 266 PrintListHeroInfo(head) 267 case 2: 268 PrintListHeroInfoByReverse(head) 269 default: 270 fmt.Println("输入查看链表的方式有误!") 271 } 272 case 5: 273 fmt.Println("已退出系统...") 274 os.Exit(0) 275 default: 276 fmt.Println("操作有误,请输入(1-4)数字!") 277 } 278 } 279 } 280 281 func main() { 282 283 //Hero 链表 头结点HeroListLinkHead 284 head := &HeroNode{} 285 286 CRUDToList(head) 287 }
-
单向环形链表(约瑟夫问题(丢手绢))
-
1 package main 2 3 import "fmt" 4 5 //Child 孩子结构体 6 type Child struct { 7 no int 8 next *Child 9 } 10 11 //AddChild 添加孩子 12 func AddChild(num int) *Child { 13 first := &Child{} 14 currentChild := &Child{} 15 if num < 1 { 16 fmt.Println("num值太少了,不够玩的") 17 return first 18 } 19 for i := 1; i <= num; i++ { 20 child := &Child{ 21 no: i, 22 } 23 if i == 1 { 24 first = child 25 currentChild = child 26 currentChild.next = first 27 } else { 28 currentChild.next = child 29 currentChild = child 30 currentChild.next = first 31 } 32 } 33 return first 34 } 35 36 //PrintChild 输出孩子链表 37 func PrintChild(first *Child) { 38 if first.next == nil { 39 fmt.Println("链表为空,没有孩子") 40 return 41 } 42 43 currentChild := first 44 for { 45 fmt.Printf("孩子编号:%v ", currentChild.no) 46 if currentChild.next == first { 47 break 48 } 49 currentChild = currentChild.next 50 } 51 } 52 53 /* 54 ThrowTheHandkerchief 丢手绢 55 56 first *Child 第一个孩子的节点 57 58 startNum int 开始从第几个孩子数 59 60 countNum int 数几下 61 */ 62 func ThrowTheHandkerchief(first *Child, startNum int, countNum int) { 63 if first.next == nil { 64 fmt.Println("空链表,请添加孩子") 65 return 66 } 67 68 tail := first 69 for { 70 if tail.next == first { 71 break 72 } 73 tail = tail.next 74 } 75 76 for i := 1; i <= startNum-1; i++ { 77 first = first.next 78 tail = tail.next 79 } 80 81 for { 82 for i := 1; i <= countNum-1; i++ { 83 first = first.next 84 tail = tail.next 85 } 86 fmt.Printf("编号为 %v 的孩子出圈了 ", first.no) 87 first = first.next 88 tail.next = first 89 if tail == first { 90 break 91 } 92 } 93 fmt.Printf("编号为 %v 的孩子最后出圈... ", first.no) 94 95 } 96 func main() { 97 firstChild := AddChild(100) 98 PrintChild(firstChild) 99 ThrowTheHandkerchief(firstChild, 99, 25) 100 }