go 链表

什么是链表

  链表是一种数据结构,链表作为一种基础的数据结构可以用来生成其它类型的数据结构。

  链表通常由一连串节点组成,节点可以在运行时动态生成,每个节点包含任意的实例数据(data fields)和存储下一个或下一个结点地址的指针域

  链表是有序的列表,数据元素的逻辑顺序是通过链表中的指针链接次序实现的

  使用链表结构可以避免在使用数组时需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大

  常用的链表方式有三种:
  1. 单链表
  2. 双向链表
  3. 循环链表

链表的基础概念

链表包含头节点(必须)、头指针、首元节点、其他节点

  • 首元结点:就是链表中存储第一个元素的结点,如下图中 a1 的位置。
  • 头结点:它是在首元结点之前附设的一个结点,其指针域指向首元结点。头结点的数据域可以存储链表的长度或者其它的信息,也可以为空不存储任何信息。
  • 头指针:它是指向链表中第一个结点的指针。若链表中有头结点,则头指针指向头结点;若链表中没有头结点,则头指针指向首元结点。

头结点在链表中不是必须的,但增加头结点有以下几点好处:

  • 增加了头结点后,首元结点的地址保存在头结点的指针域中,对链表的第一个数据元素的操作与其他数据元素相同,无需进行特殊处理。
  • 增加头结点后,无论链表是否为空,头指针都是指向头结点的非空指针,若链表为空的话,那么头结点的指针域为空

go 链表_第1张图片

单向链表

单链表的形式如下图所示
image.png

实现一个单链表

package main

import (
    "fmt"
)

//定义一个 HeroNode
type HeroNode struct {
    no int
    name  string
    nickname string
    next  *HeroNode //这个表示指向下一个结点
}

//给链表插入一个结点
//编写第一种插入方法,在单链表的最后加入
func InsertHeroNode(head *HeroNode, newHeroNode *HeroNode) {
    //1. 先找到该链表的最后这个结点
    //2. 创建一个辅助结点
    temp := head
    for {
        if temp.next == nil { //表示找到最后
            break
        }
        temp = temp.next //  让 temp 不断的指向下一个结点
    }

    //3. 将 newHeroNode 加入到链表的最后
    temp.next = newHeroNode
}

//给链表插入一个结点
//编写第 2 种插入方法,根据 no  的编号从小到大插入..【实用】
func InsertHeroNode2(head *HeroNode, newHeroNode *HeroNode) {
    //1. 找到适当的结点
    //2. 创建一个辅助结点[跑龙套, 帮忙]
    temp := head
    flag := true
    //让插入的结点的 no,和 temp 的下一个结点的 no 比较
    for {

        if temp.next == nil {
            //说明到链表的最后
            break
        } else if temp.next.no >= newHeroNode.no {
            //说明 newHeroNode 就应该插入到 temp 后面
            break
        } else if temp.next.no == newHeroNode.no {
            //说明我们额链表中已经有这个 no,就不然插入. flag = false
            break
        }
        temp = temp.next
    }

    if !flag {
        fmt.Println("对不起,已经存在 no=", newHeroNode.no)
        return
    } else {
        newHeroNode.next = temp.next
        temp.next = newHeroNode
    }
}

//显示链表的所有结点信息
func ListHeroNode(head *HeroNode) {
    //1. 创建一个辅助结点
    temp := head

    // 先判断该链表是不是一个空的链表
    if temp.next == nil {
        fmt.Println("空空如也。。。。")
        return
    }
    //2. 遍历这个链表
    for {
        fmt.Printf("[%d , %s , %s]==>", temp.next.no, temp.next.name, temp.next.nickname)
        //判断是否链表后
        temp = temp.next
        if temp.next == nil {
            break
        }
    }
}

func main() {
    //1. 先创建一个头结点
    head := &HeroNode{}
    hero1 := &HeroNode{
        no : 1,
        name : "张三",
        nickname : "法外狂徒",
    }
    hero2 := &HeroNode{
        no : 2,
        name : "王五",
        nickname : "隔壁老王",
    }
    hero3 := &HeroNode{
        no : 3,
        name : "李四",
        nickname : "好人老四",
    }
    //3. 加入
    InsertHeroNode2(head, hero3)
    InsertHeroNode2(head, hero1)
    InsertHeroNode2(head, hero2)

    // 4. 显示
    ListHeroNode(head)
}

执行输出结果

>go run main.go

[1 , 张三 , 法外狂徒]==>[2 , 王五 , 隔壁老王]==>[3 , 李四 , 好人老四]==>

你可能感兴趣的:(go链表)