• go语言|数据结构:单链表(1)


    目录

    链表

     单链表结构

    创建节点

    遍历链表

    头插法

    尾插法

    遍历方法

    链表长度

    链表转数组

    数组转链表


    链表

      一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。使用链表结构可以避免在使用数组时需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。

     单链表结构

      利用 struct 可以包容多种数据类型,结构体内也可以包含多个成员,这些成员可以是基本类型、自定义类型、数组类型,也可以是指针类型。这里可以使用指针类型成员来存放下一个结点的地址。如以下定义,成员 data 用来存放结点中的数据(整数类型),next 是指针类型的成员,它指向 ListNode struct 类型数据,也就是下一个结点的数据类型。

    1. type ListNode struct {
    2. data int
    3. next *ListNode
    4. }

    创建节点

    节点声明和赋值有以下几种格式:

    1. package main
    2. import "fmt"
    3. type ListNode struct {
    4. data int
    5. next *ListNode
    6. }
    7. func main() {
    8. var head *ListNode
    9. head = new(ListNode)
    10. head.data = 1
    11. var node1 = new(ListNode)
    12. node1.data = 2
    13. var node2 = &ListNode{3, nil}
    14. var node3 = &ListNode{data: 4}
    15. fmt.Println(*head)
    16. fmt.Println(*node1)
    17. fmt.Println(*node2)
    18. fmt.Println(*node3)
    19. }
    20. /* 输出:
    21. {1 }
    22. {2 }
    23. {3 }
    24. {4 }
    25. */

    遍历链表

    一个for循环即可,结构描述的链表没有空链表的,不论data是何种类型,一旦声明即使不马上赋值也会有类型默认值,比如new(ListNode)即赋值了ListNode{0, nil}。

    1. func showNode(p *ListNode) {
    2. fmt.Print(*p)
    3. for p.next != nil {
    4. p = p.next
    5. fmt.Print("->", *p)
    6. }
    7. fmt.Println()
    8. }

    头插法

    新结点放在链表的最前面

    1. package main
    2. import "fmt"
    3. type ListNode struct {
    4. data int
    5. next *ListNode
    6. }
    7. func showNode(p *ListNode) {
    8. fmt.Print(*p)
    9. for p.next != nil {
    10. p = p.next
    11. fmt.Print("->", *p)
    12. }
    13. fmt.Println()
    14. }
    15. func main() {
    16. var head = &ListNode{0, nil}
    17. for i := 1; i < 5; i++ {
    18. var node = ListNode{data: i}
    19. node.next = head
    20. head = &node
    21. }
    22. showNode(head)
    23. }
    24. /* 输出:
    25. {4 0xc000084250}->{3 0xc000084240}->{2 0xc000084230}->{1 0xc000084220}->{0 }
    26. */

    尾插法

    新结点追加到链表的最后面

    1. package main
    2. import "fmt"
    3. type ListNode struct {
    4. data int
    5. next *ListNode
    6. }
    7. func showNode(p *ListNode) {
    8. fmt.Print(*p)
    9. for p.next != nil {
    10. p = p.next
    11. fmt.Print("->", *p)
    12. }
    13. fmt.Println()
    14. }
    15. func main() {
    16. var head, tail *ListNode
    17. head = &ListNode{0, nil}
    18. tail = head
    19. for i := 1; i < 5; i++ {
    20. var node = ListNode{data: i}
    21. (*tail).next = &node
    22. tail = &node
    23. }
    24. showNode(head)
    25. }
    26. /* 输出:
    27. {0 0xc000084220}->{1 0xc000084230}->{2 0xc000084240}->{3 0xc000084250}->{4 }
    28. */

    遍历方法

    方法的定义:参数表放在函数名前

    1. package main
    2. import "fmt"
    3. type ListNode struct {
    4. data int
    5. next *ListNode
    6. }
    7. func (p *ListNode) travel() {
    8. fmt.Print(p.data)
    9. for p.next != nil {
    10. p = p.next
    11. fmt.Print("->", p.data)
    12. }
    13. fmt.Println("")
    14. }
    15. func main() {
    16. var head = &ListNode{0, nil}
    17. head.travel()
    18. for i := 1; i < 10; i++ {
    19. var node = ListNode{data: i}
    20. node.next = head
    21. head = &node
    22. }
    23. head.travel()
    24. var root *ListNode
    25. root = new(ListNode)
    26. root.travel()
    27. }
    28. /* 输出:
    29. 0
    30. 9->8->7->6->5->4->3->2->1->0
    31. 0
    32. */

    链表长度

    注意:函数与方法的区别

    1. package main
    2. import "fmt"
    3. type ListNode struct {
    4. data int
    5. next *ListNode
    6. }
    7. func (head *ListNode) size() int {
    8. size := 1
    9. for head = head.next; head != nil; size++ {
    10. head = head.next
    11. }
    12. return size
    13. }
    14. func Len(head *ListNode) int {
    15. size := 1
    16. for head = head.next; head != nil; size++ {
    17. head = head.next
    18. }
    19. return size
    20. }
    21. func main() {
    22. var head = &ListNode{0, nil}
    23. fmt.Println(Len(head))
    24. fmt.Println(head.size())
    25. for i := 1; i < 10; i++ {
    26. var node = ListNode{data: i}
    27. node.next = head
    28. head = &node
    29. }
    30. fmt.Println(Len(head))
    31. fmt.Println(head.size())
    32. }
    33. /* 输出:
    34. 1
    35. 1
    36. 10
    37. 10
    38. */

    链表转数组

    1. package main
    2. import (
    3. "fmt"
    4. )
    5. type ListNode struct {
    6. data int
    7. next *ListNode
    8. }
    9. func (head *ListNode) size() int {
    10. size := 1
    11. for head = head.next; head != nil; size++ {
    12. head = head.next
    13. }
    14. return size
    15. }
    16. func (head *ListNode) tolist() []int {
    17. var res []int
    18. res = make([]int, 0, head.size())
    19. for head.next != nil {
    20. res = append(res, head.data)
    21. head = head.next
    22. }
    23. res = append(res, head.data)
    24. return res
    25. }
    26. func (head *ListNode) tolist2() []int {
    27. var res []int
    28. res = make([]int, 0, head.size())
    29. res = append(res, head.data)
    30. head = head.next
    31. for head != nil {
    32. res = append(res, head.data)
    33. head = head.next
    34. }
    35. return res
    36. }
    37. func main() {
    38. var head = &ListNode{0, nil}
    39. for i := 1; i < 10; i++ {
    40. var node = ListNode{data: i}
    41. node.next = head
    42. head = &node
    43. }
    44. fmt.Println(head.tolist())
    45. var root, tail *ListNode
    46. root = &ListNode{0, nil}
    47. tail = root
    48. for i := 1; i < 10; i++ {
    49. var node = ListNode{data: i}
    50. (*tail).next = &node
    51. tail = &node
    52. }
    53. fmt.Println(root.tolist2())
    54. }
    55. /* 输出:
    56. [9 8 7 6 5 4 3 2 1 0]
    57. [0 1 2 3 4 5 6 7 8 9]
    58. */

    数组转链表

    1. package main
    2. import "fmt"
    3. type ListNode struct {
    4. data int
    5. next *ListNode
    6. }
    7. func (p *ListNode) travel() {
    8. fmt.Print(p.data)
    9. for p.next != nil {
    10. p = p.next
    11. fmt.Print("->", p.data)
    12. }
    13. fmt.Println("")
    14. }
    15. func toNode(list []int) *ListNode {
    16. var head, tail *ListNode
    17. head = &ListNode{list[0], nil}
    18. tail = head
    19. for i := 1; i < len(list); i++ {
    20. var node = ListNode{data: list[i]}
    21. (*tail).next = &node
    22. tail = &node
    23. }
    24. return head
    25. }
    26. func main() {
    27. var lst = []int{1, 3, 2, 3, 5, 6, 6, 8, 9}
    28. toNode(lst).travel()
    29. }
    30. /* 输出:
    31. 1->3->2->3->5->6->6->8->9
    32. */

    例题

    实战一:
    给定一个已排序链表,删除重复节点,原始链表中多次出现的数字只能保留一次。

    示例1

    输入: 1->1->2
    输出: 1->2

    示例2

    输入: 1->1->2->3->3
    输出: 1->2->3


    实战二:
    给定一个排序链表,删除所有重复的节点,留原始链表有过重复的数字一个也不留。

    示例1

    输入: 1->2->3->3->4->4->5
    输出: 1->2->5

    示例2

    输入: 1->1->1->2->3
    输出: 2->3


    实战三:
    给定两个有序链表(升序),合并为一个新的有序链表并返回。

    示例1

    输入:1->2>4->8
       1->3->3->5->5
    输出:1->1->2->3->3->4->5->5->8

    示例2

    输入:0->2>4->8
       1->3->5->7->9
    输出:0->1->2->3->4->5->6->7->8->9


    答案见下集——

  • 相关阅读:
    【Attack】针对GNN-based假新闻检测器
    Java8 新特性之Stream(七)-- Stream的reduce()详细用法
    Android切换主题生命周期流程与onSaveInstanceState和onRestoreInstanceState,Kotlin
    H5游戏分享-全民找房祖名qmxzfzm
    GFS 分布式文件系统
    合宙Air724UG LuatOS-Air LVGL API控件-滑动条 (Slider)
    Redis十大数据类型
    ES6新特性 面试高频题1
    算法练习8——有序三元组中的最大值
    测试自学人必看:软件测试如何找测试项目?
  • 原文地址:https://blog.csdn.net/boysoft2002/article/details/126442832