双链表算法

た 入场券 2023-07-12 14:42 118阅读 0赞
  • 双链表最大的优势就是可以双向遍历

    package main

    import “fmt”

    type Node struct {

    1. num int
    2. name string
    3. pre *Node
    4. next *Node

    }

    // 末尾插入
    func insert(head Node, newNode Node) {

    1. tmp := head
    2. for {
    3. // 插入末尾,先连接左边,后连接右边
    4. if tmp.next == nil {
    5. tmp.next = newNode
    6. newNode.pre = tmp
    7. break
    8. }
    9. tmp = tmp.next
    10. }

    }

    // 正向遍历
    func list(head *Node) {

    1. tmp := head
    2. if tmp.next == nil {
    3. fmt.Printf("link is null")
    4. }
    5. for {
    6. if tmp.next != nil {
    7. // 第一个tmp代表head的下一个
    8. fmt.Printf("[%d] = %s \n", tmp.next.num, tmp.next.name)
    9. } else {
    10. break
    11. }
    12. tmp = tmp.next
    13. }

    }

    // 反向遍历
    func reverselist(head *Node) {

    1. tmp := head
    2. if tmp.next == nil {
    3. fmt.Printf("link is null")
    4. }
    5. // 先将tmp指向链表末尾
    6. for {
    7. if tmp.next == nil {
    8. break
    9. }
    10. tmp = tmp.next
    11. }
    12. for {
    13. // 注意头节点并不是空的,里面还有mext和pre
    14. if tmp.pre != nil {
    15. fmt.Printf("[%d] = %s \n", tmp.num, tmp.name)
    16. } else {
    17. break
    18. }
    19. tmp = tmp.pre
    20. }

    }

    func main() {

    1. // head是随机位置的指针
    2. head := &Node{ }
    3. // 插入数据不需传递下一个node地址
    4. node := &Node{
    5. num: 1,
    6. name: "amber",
    7. }
    8. node2 := &Node{
    9. num: 2,
    10. name: "alice",
    11. }
    12. node3 := &Node{
    13. num: 3,
    14. name: "necy",
    15. }
    16. node4 := &Node{
    17. num: 4,
    18. name: "bella",
    19. }
    20. insert(head, node)
    21. insert(head, node2)
    22. insert(head, node3)
    23. insert(head, node4)
    24. list(head)
    25. fmt.Println()
    26. reverselist(head)

    }

输出结果:
在这里插入图片描述

  • 双链表有序插入和删除

    package main

    import “fmt”

    type Node struct {

    1. num int
    2. name string
    3. pre *Node
    4. next *Node

    }

    func orderInsert(head Node, newNode Node) {

    1. tmp := head
    2. for {
    3. // 必须放在前面,防止在末尾nil,被插在最后
    4. if newNode.num == tmp.num {
    5. fmt.Printf("node has already in link\n")
    6. break
    7. }
    8. // 放在第二顺位,当未找到插入最后
    9. if tmp.next == nil {
    10. tmp.next = newNode
    11. newNode.pre = tmp
    12. break
    13. }
    14. // 遍历是从前往后,判断条件tmp.next是保证在tmp后面插入前插入
    15. if newNode.num < tmp.next.num {
    16. // 先关联右边,再关联左边
    17. newNode.next = tmp.next
    18. newNode.pre = tmp
    19. tmp.next.pre = newNode
    20. tmp.next = newNode
    21. break
    22. }
    23. tmp = tmp.next
    24. }

    }

    func list(head *Node) {

    1. tmp := head
    2. if tmp.next == nil {
    3. fmt.Printf("link is null")
    4. }
    5. for {
    6. if tmp.next != nil {
    7. // 第一个tmp代表head的下一个
    8. fmt.Printf("[%d] = %s \n", tmp.next.num, tmp.next.name)
    9. } else {
    10. break
    11. }
    12. tmp = tmp.next
    13. }

    }

    func delete(head *Node, num int) {

    1. tmp := head
    2. for {
    3. if tmp == nil {
    4. fmt.Printf("link is null")
    5. break
    6. }
    7. // 注意这里要找到tmp.next,因为找到tmp是要删除节点无法删除
    8. if tmp.num == num {
    9. if tmp.next == nil {
    10. tmp.pre.next = nil
    11. break
    12. } else {
    13. tmp.next.pre = tmp.pre
    14. tmp.pre.next = tmp.next
    15. break
    16. }
    17. }
    18. tmp = tmp.next
    19. }

    }

    func main() {

    1. // head是随机位置的指针
    2. head := &Node{ }
    3. // 插入数据不需传递下一个node地址
    4. node := &Node{
    5. num: 1,
    6. name: "amber",
    7. }
    8. node2 := &Node{
    9. num: 2,
    10. name: "alice",
    11. }
    12. node3 := &Node{
    13. num: 3,
    14. name: "necy",
    15. }
    16. node4 := &Node{
    17. num: 3,
    18. name: "zoe",
    19. }
    20. orderInsert(head, node4)
    21. orderInsert(head, node2)
    22. orderInsert(head, node)
    23. orderInsert(head, node3)
    24. list(head)
    25. fmt.Printf("****************\n")
    26. delete(head, 2)
    27. list(head)

    }

输出结果:
在这里插入图片描述
PS:这里演示的是重复插入在最后的情况,所以要将重复判断放在末尾插入之前

总结:
1、无论单链表还是双链表插入一定定位在tmp和tmp.next之间
2、头节点数据是空的,但不代表头节点=nil
3、删除和插入是一定要考虑删除的恰好是最后的节点或者插入到最后的情况

发表评论

表情:
评论列表 (有 0 条评论,118人围观)

还没有评论,来说两句吧...

相关阅读

    相关

    双向链表 双向链表中,每个结点都有两个指针域,一个指向其后继结点,另一个指针指向其前驱结点,如图1.1(a)所示,因此,可以从某个结点开始朝两个方向遍历整个链表。