單鏈表 常用操作(golang)

(單鏈表備忘記錄)
知識(shí)點(diǎn):

  1. 單鏈表結(jié)構(gòu)
  2. 創(chuàng)建鏈表方法
    1. 頭插法創(chuàng)建
    2. 尾插法創(chuàng)建
  3. 遍歷鏈表
  4. 逆序反轉(zhuǎn)鏈表
    1. 迭代
    2. 遞歸
    3. 頭插法
    4. 就地逆置
  5. 判斷鏈表中是否有環(huán)
  6. 鏈表中環(huán)的入口點(diǎn)
  7. 鏈表中環(huán)的長度
  8. 鏈表總長度


1. 單鏈表結(jié)構(gòu)

data. 數(shù)據(jù)
next. 指向下一個(gè)鏈表節(jié)點(diǎn)的指針

type Node struct {
    data int
    next *Node
}

2. 創(chuàng)建鏈表方法

簡單的可以一行行敲著創(chuàng)建,先創(chuàng)建node1纪吮,然后node2,
然后鏈起來node1.next=&node2
1. 頭插法創(chuàng)建

/*頭插法 創(chuàng)建鏈表*/
func CreateNodeInsterOnHead(listData []int) *Node {
    if len(listData) == 0 {
        return &Node{data: 0}
    }
    head := &Node{data: listData[0]}
    for _, v := range listData[1:] {
        node := &Node{data: v}
        node.next = head //新節(jié)點(diǎn)的next指向頭head
        head = node//頭head換成新節(jié)點(diǎn)
    }
    return head
}

傳入 「1 2 3 4 5 6 7 8 9 10」
輸出 「10 9 8 7 6 5 4 3 2 1」
2. 尾插法創(chuàng)建

/*尾插法創(chuàng)建鏈表*/
func CreateNodeInsterOnTail(listData []int) *Node {
    if len(listData) == 0 {
        return &Node{data: 0}
    }
    head := &Node{data: listData[0]}
    end := head //end 記錄鏈表的尾,不斷向end后插入新節(jié)點(diǎn)
    for _, v := range listData[1:] {
        end.next = &Node{data: v}
        end = end.next //移動(dòng)end指針,指向新的尾節(jié)點(diǎn)
    }
    return head
}

傳入 「1 2 3 4 5 6 7 8 9 10」
輸出 「1 2 3 4 5 6 7 8 9 10」

3. 遍歷鏈表

func printNode(node *Node) {
    if node == nil || node.next == nil {
        return
    }
    cur := node
    for cur != nil {
        fmt.Printf("%d ", cur.data)
        cur = cur.next
    }
}

4. 逆序反轉(zhuǎn)鏈表

4.1 迭代
func ReverseNode1(head *Node) *Node {
    if head == nil || head.next == nil {
        return head
    }
    var prev *Node = nil
    var cur *Node = head
    var end *Node = head.next
    for {
        cur.next = prev //當(dāng)前結(jié)點(diǎn)指向前一個(gè)節(jié)點(diǎn)
        if end == nil {
            break
        }
        prev = cur     //指針后移
        cur = end      //指針后移,處理下一個(gè)節(jié)點(diǎn)
        end = end.next //temp作為中間節(jié)點(diǎn)进泼,記錄當(dāng)前結(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)的位置
    }
    head = cur
    return head
}

4.2 遞歸
func ReverseNode2(head *Node) *Node {
    if head == nil || head.next == nil {//遞歸的出口
        return head
    } else {
        //一直遞歸城瞎,找到鏈表中最后一個(gè)節(jié)點(diǎn)
        new_head := ReverseNode2(head.next)

        //當(dāng)逐層退出時(shí),new_head 的指向都不變惶桐,一直指向原鏈表中最后一個(gè)節(jié)點(diǎn);
        //遞歸每退出一層潘懊,函數(shù)中 head 指針的指向都會(huì)發(fā)生改變姚糊,都指向上一個(gè)節(jié)點(diǎn)。

        //每退出一層授舟,都需要改變 head->next 節(jié)點(diǎn)指針域的指向救恨,同時(shí)令 head 所指節(jié)點(diǎn)的指針域?yàn)?NULL。
        head.next.next = head
        head.next = nil
        //每一層遞歸結(jié)束释树,都要將新的頭指針返回給上一層肠槽。由此擎淤,即可保證整個(gè)遞歸過程中,能夠一直找得到新鏈表的表頭秸仙。
        return new_head
    }
}
4.3 頭插法
func ReverseNode3(head *Node) *Node {
    var new_head *Node = nil
    var temp *Node = nil
    if head == nil || head.next == nil {
        return head
    }
    for head != nil {
        temp = head
        //將 temp 從 head 中摘除
        head = head.next
        //將 temp 插入到 new_head 的頭部
        temp.next = new_head
        new_head = temp
    }
    return new_head
}
4.4 就地逆置
func ReverseNode4(head *Node) *Node {
    var beg *Node = nil
    var end *Node = nil
    if head == nil || head.next == nil {
        return head
    }
    beg = head
    end = head.next
    for end != nil {
        //將 end 從鏈表中摘除
        beg.next = end.next
        //將 end 移動(dòng)至鏈表頭
        end.next = head
        head = end
        //調(diào)整 end 的指向嘴拢,另其指向 beg 后的一個(gè)節(jié)點(diǎn),為反轉(zhuǎn)下一個(gè)節(jié)點(diǎn)做準(zhǔn)備
        end = beg.next
    }
    return head
}

5. 判斷鏈表中是否有環(huán)

快慢指針

/*
* 鏈表是否有環(huán)
* is 是否
* meet 有環(huán)是返回快慢指針的相遇節(jié)點(diǎn)
*/
func isRingLinkNode(head *Node) (is bool, meet *Node) {
    slow := head
    fast := head
    for fast != nil && fast.next != nil {
        slow = slow.next
        fast = fast.next.next
        if slow == fast {
            return true, slow
        }
    }
    return false, nil
}

6. 鏈表中環(huán)的入口點(diǎn)

func findRingeEntry(head *Node) *Node {
    slow := head
    fast := head
    for fast != nil && fast.next != nil {
        slow = slow.next
        fast = fast.next.next
        if slow == fast {
            break
        }
    }

    if fast == nil || fast.next == nil {
        return nil
    }
    slow = head //慢指針重新指向頭節(jié)點(diǎn)
    for slow != fast {
        slow = slow.next
        fast = fast.next
    }
    return slow
}

相遇后寂纪,slow繼續(xù)一次移動(dòng)一個(gè)節(jié)點(diǎn)席吴,新另一node從鏈表頭開始一次移動(dòng)一個(gè)節(jié)點(diǎn)。

7. 鏈表中環(huán)的長度

//計(jì)算單鏈表環(huán)的長度
func ringLength(head *Node) int {
    //首先通過上面的方法判斷弊攘,鏈表是否有環(huán)抢腐,并返回快慢指針的相遇點(diǎn)
    is, meet := isRingLinkNode(head)
    if is == false {
        return 0 //沒有環(huán),則直接返回
    }
    tmp := meet //tmp 停留在相遇點(diǎn)不再移動(dòng)
    meet = meet.next
    len := 1
    for tmp != meet {
        len++
        meet = meet.next
    }
    return len
}

先用快慢指針相遇襟交,相遇后記錄相遇點(diǎn)迈倍,然后繼續(xù)next向下走并記錄走了幾步,
再次相遇時(shí)即環(huán)長度捣域。

8. 鏈表總長度

總長度 = 頭到入口點(diǎn)長度 + 環(huán)到長度

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末啼染,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子焕梅,更是在濱河造成了極大的恐慌迹鹅,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,820評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件贞言,死亡現(xiàn)場離奇詭異斜棚,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)该窗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門弟蚀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人酗失,你說我怎么就攤上這事义钉。” “怎么了规肴?”我有些...
    開封第一講書人閱讀 168,324評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵捶闸,是天一觀的道長。 經(jīng)常有香客問我拖刃,道長删壮,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,714評(píng)論 1 297
  • 正文 為了忘掉前任兑牡,我火速辦了婚禮央碟,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘发绢。我一直安慰自己硬耍,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,724評(píng)論 6 397
  • 文/花漫 我一把揭開白布边酒。 她就那樣靜靜地躺著经柴,像睡著了一般。 火紅的嫁衣襯著肌膚如雪墩朦。 梳的紋絲不亂的頭發(fā)上坯认,一...
    開封第一講書人閱讀 52,328評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音氓涣,去河邊找鬼牛哺。 笑死,一個(gè)胖子當(dāng)著我的面吹牛劳吠,可吹牛的內(nèi)容都是我干的引润。 我是一名探鬼主播,決...
    沈念sama閱讀 40,897評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼痒玩,長吁一口氣:“原來是場噩夢啊……” “哼淳附!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蠢古,我...
    開封第一講書人閱讀 39,804評(píng)論 0 276
  • 序言:老撾萬榮一對情侶失蹤奴曙,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后草讶,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體洽糟,經(jīng)...
    沈念sama閱讀 46,345評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,431評(píng)論 3 340
  • 正文 我和宋清朗相戀三年堕战,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了坤溃。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,561評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡践啄,死狀恐怖浇雹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情屿讽,我是刑警寧澤昭灵,帶...
    沈念sama閱讀 36,238評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站伐谈,受9級(jí)特大地震影響烂完,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜诵棵,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,928評(píng)論 3 334
  • 文/蒙蒙 一抠蚣、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧履澳,春花似錦嘶窄、人聲如沸怀跛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽吻谋。三九已至,卻和暖如春现横,著一層夾襖步出監(jiān)牢的瞬間漓拾,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評(píng)論 1 272
  • 我被黑心中介騙來泰國打工戒祠, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留骇两,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,983評(píng)論 3 376
  • 正文 我出身青樓姜盈,卻偏偏與公主長得像低千,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子馏颂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,573評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 搞懂單鏈表常見面試題 Hello 繼上次的 搞懂基本排序算法栋操,這個(gè)一星期,我總結(jié)了饱亮,我所學(xué)習(xí)和思考的單鏈表基礎(chǔ)知識(shí)...
    醒著的碼者閱讀 4,591評(píng)論 1 45
  • 涉及到單鏈表的基本操作有如下: int initList(linkList *);//初始化一個(gè)單鏈表矾芙,具有頭指針...
    keeeeeenon閱讀 2,057評(píng)論 0 1
  • 前言 本文是題主準(zhǔn)備面試時(shí)記錄下的筆記整理而來,稍顯粗陋近上,還請各位擼友勿噴哈剔宪! Topic 目錄數(shù)組字符串鏈表二叉...
    rh_Jameson閱讀 1,538評(píng)論 1 10
  • 單鏈表 單鏈表問題與思路 找出單鏈表的倒數(shù)第K個(gè)元素(僅允許遍歷一遍鏈表)使用指針追趕的方法。定義兩個(gè)指針fast...
    wxkkkkk閱讀 601評(píng)論 0 0
  • 表情是什么壹无,我認(rèn)為表情就是表現(xiàn)出來的情緒葱绒。表情可以傳達(dá)很多信息。高興了當(dāng)然就笑了斗锭,難過就哭了地淀。兩者是相互影響密不可...
    Persistenc_6aea閱讀 125,314評(píng)論 2 7