線性表的鏈式存儲,以及使用快慢指針找不知長度鏈表的中間節點
題目描述
首先,給定一個帶有頭結點 head 的不知長度鏈表,返回鏈表的中間結點。
如果有兩個中間結點,則返回第二個中間結點。注意鏈表長度未知,這里測試定義的鏈表結構體存儲的數據類型可以用字符串類型。
示例說明:
實例1
輸入:“one”-"two"-"three"-"four"-"five"
輸出:鏈表的中間節點為 ["three"]
實例2
輸入:“tom”-"jack"-"kaka"-"James"-"vickor"-"wade"-"aha"-"tiger"
輸出:鏈表的中間節點為 ["James","vickor"]
解題思路
設置兩個指針,一個快指針,每次走兩步,一個慢指針,每次走一步,當快指針為空(偶數個節點)或者快指針的next指針指向空時(奇數個節點),此時慢指針即為中間節點。
步驟:
首先定義線性表的鏈式存儲,單個節點的定義如下
type Node struct { // 定義一個node結構體
data string
next *Node
}
緊接著定義相應的方法,主要有增加節點Append、獲取長度GetLength、獲取中間節點GetCenterNode等。
在鏈表尾部增加節點:
func (n *Node) Append(data string){
createNode := &Node{data,nil}
for n.next != nil{
n = n.next
}
n.next = createNode
}
獲取整個鏈表的長度:
func (n *Node) GetLength() int{
if n.next==nil{
return 0
}
length:= 0
for n.next!=nil{
length ++
n = n.next
}
return length
}
獲取整個鏈表中間節點:(這里有對不同情況分別討論,如一些邊界條件、鏈表長度為奇數偶數時分別討論)
func (n Node)GetCenterNode()[]string{
str := make([]string,0,2)
if n.next==nil{
return nil
}
l := n.next
s := n.next
for s.next!= nil{
// 單數情況
if l.next==nil{
str = append(str, s.data)
return str
}
// 雙數情況
if l.next != nil && l.next.next == nil{
str = append(str,s.data)
str = append(str,s.next.data)
return str
}
s =s.next
l = l.next.next
}
return str
}
首先初始化一個鏈表
// 初始化一個鏈表
func initLinkList ()Node{
return &Node{"genesis node", nil}
}
通過隨機數拼接生成一個長度為20的隨機鏈表,用于測試
func Rand20List(n *Node){
for i:=0;i<3;i++{
n.Append("this is "+strconv.Itoa(i))
}
}
通過main函數進行測試,當然也可通過寫測試函數進行測試。
func main(){
link := initLinkList()
var s int
for {
fmt.Println("1.查看鏈表")
fmt.Println("2.創建鏈表20個數據")
fmt.Println("3.鏈表長度")
fmt.Println("4.查看中間節點值")
fmt.Println("5.退出")
fmt.Println("請輸入選擇:")
fmt.Scan(&s)
switch s {
case 1:
fmt.Println(link.MapLinkList())
case 2:
Rand20List(link)
case 3:
fmt.Println(link.GetLength())
case 4:
fmt.Println(link.GetCenterNode())
case 5:
return
}
}
}
完整代碼
完整線性表的鏈式存儲,以及使用快慢指針找不知長度鏈表的中間節點代碼如下:
package main
import (
"fmt"
"strconv"
)
// 定義一個node結構體
type Node struct {
data string
next *Node
}
func (n *Node) Append(data string){
createNode := &Node{data,nil}
for n.next != nil{
n = n.next
}
n.next = createNode
}
func (n *Node) GetLength() int{
if n.next==nil{
return 0
}
length:= 0
for n.next!=nil{
length ++
n = n.next
}
return length
}
func (n *Node) MapLinkList()[]string{
var str []string
if n.next == nil{
return nil
}
for n.next != nil{
str = append(str,n.next.data)
n = n.next
}
return str
}
// 快慢指針法求不知道長度的鏈表的中間值
func (n *Node)GetCenterNode()[]string{
str := make([]string,0,2)
if n.next==nil{
return nil
}
l := n.next
s := n.next
for s.next!= nil{
// 單數情況
if l.next==nil{
str = append(str, s.data)
return str
}
// 雙數情況
if l.next != nil && l.next.next == nil{
str = append(str,s.data)
str = append(str,s.next.data)
return str
}
s =s.next
l = l.next.next
}
return str
}
// 初始化一個鏈表
func initLinkList ()*Node{
return &Node{"genesis node", nil}
}
func Rand20List(n *Node){
for i:=0;i<3;i++{
n.Append("this is "+strconv.Itoa(i))
}
}
func main(){
link := initLinkList()
var s int
for {
fmt.Println("1.查看鏈表")
fmt.Println("2.創建鏈表20個數據")
fmt.Println("3.鏈表長度")
fmt.Println("4.查看中間節點值")
fmt.Println("5.退出")
fmt.Println("請輸入選擇:")
fmt.Scan(&s)
switch s {
case 1:
fmt.Println(link.MapLinkList())
case 2:
Rand20List(link)
case 3:
fmt.Println(link.GetLength())
case 4:
fmt.Println(link.GetCenterNode())
case 5:
return
}
}
}
最后,通往北京的路有很多條,你也可以有其他更好的方法,歡迎一起交流學習,共同進步。