golang之链表及二叉树实现

138 阅读2分钟

链表

链表是一种数据结构,它由一系列节点组成,每个节点包含数据和指向下一个节点的指针。链表中的节点可以按照任意顺序排列,它们通过指针相互连接起来。与数组不同,链表的节点不需要在内存中连续存储。链表通常用于需要频繁插入或删除元素的场景,因为其插入和删除的时间复杂度低。

单项链表

package main

import "fmt"

type Student struct {
    Name string
    age  int
    next *Student
    //指向这个结构体的指针地址
}

func main() {

    //头部结构体
    var head Student
    head.Name = "zhangsan"
    head.age = 20

    //第二个结构体
    var stu1 Student
    stu1.Name = "lisi"
    stu1.age = 22

    //头部指向第二个结构体指针地址
    head.next = &stu1

    //第三个结构体
    var stu2 Student
    stu2.Name = "wangwu"
    stu2.age = 26

    //第二个指向第三个结构体地址
    stu1.next = &stu2

    Rey(&head)
    //定义结构体指针 从头部索引
    //var a *Student = &head

}

func Rey(a *Student) {

    //遍历输出链表中每一个结构体
    //直到a不等于空,也就是next的下一跳为空时结束循环
    for a != nil {
        fmt.Println(*a)
        a = a.next
        //让a成为下一条的链表,如此循环,直到a为nil
    }

}

输出结果

{zhangsan 20 0xc00011c3a0} 
{lisi 22 0xc00011c3c0} 
{wangwu 26 <nil>}

链表实现增删改查

package main

import (
    "fmt"
)

type Head struct {
    User string
    next *Head //链表
}

func AddHead(h **Head) {
    for i := 0; i < 10; i++ {
        //生成一个新链表
        var AddHead Head = Head{
            User: fmt.Sprintf("node%d", i+1),
        }
        //新链表的下一跳指向h的地址
        AddHead.next = *h
        //将h的地址转换成新链表
        *h = &AddHead
    }
}

//输出链表,和上面写法一样
func Rey(list *Head) {
    for list != nil {
        fmt.Println(*list)
        list = list.next
    }
}

func main() {

    //头部链表
    var head *Head = &Head{User: "张三"}

    //调用头部添加的链表
    AddHead(&head)
    //从头部索引
    Rey(head)

}

运行结果

{node10 0xc0000c2600}
{node9 0xc0000c25d0}
{node8 0xc0000c25a0}
{node7 0xc0000c2570}
{node6 0xc0000c2540}
{node5 0xc0000c2510}
{node4 0xc0000c24e0}
{node3 0xc0000c24b0}
{node2 0xc0000c2480}
{node1 0xc0000c2450}
{张三 <nil>}

尾添加链表

package main

import (
    "fmt"
)

//链表的增删改查
//首先定义结构体
type Head struct {
    User string
    pwd  string
    next *Head //链表
}

//尾部添加
func AddTail(a *Head) {
    for i := 0; i < 10; i++ {
        var AddTail Head = Head{
            User: fmt.Sprintf("node%d", i+1),
            pwd:  fmt.Sprintf("love%d", i),
        }
        a.next = &AddTail
        a = &AddTail
    }
}
//遍历链表
func Rey(list *Head) {
    for list != nil {
        fmt.Println(*list)
        //让list变为下一结构体地址
        list = list.next
    }
}
func main() {
    //头部链表
    var head *Head = &Head{
        User: "张三",
        pwd:  "love789",
    }
    //从尾部添加的链表
    AddTail(head)

    //从头部索引
    Rey(head)

}

从中间任意添加链表

package main

import (
    "fmt"
)

//链表的增删改查
//首先定义结构体
type Head struct {
    User string
    pwd  string
    next *Head //链表
}


//头部添加

func AddHead(h **Head) {
    for i := 0; i < 10; i++ {
            var AddHead Head = Head{
                    User: fmt.Sprintf("node%d", i+1),
                    pwd:  fmt.Sprintf("love%d", i),
            }
            AddHead.next = *h
            *h = &AddHead
    }
}

//任意位置添加链表
func AddRandom(a *Head, n *Head) {
    for a != nil {
            if a.User == "node2" {

                    //切换next
                    n.next = a.next
                    a.next = n
            }
            a = a.next
    }
}

//遍历链表
func Rey(list *Head) {

    for list != nil {
            fmt.Println(*list)
            //让list变为下一结构体地址
            list = list.next
    }
}
func main() {

    //头部链表
    var head *Head = &Head{
            User: "张三",
            pwd:  "love789",
    }

    定义一个中间连接的链表块
     var NewHead = &Head{
            User: "王五",
            pwd:  "123456",
    }

    //调用头部添加的链表
    AddHead(&head)

    //调用任意位置添加的链表
    AddRandom(head, NewHead)

    //从头部索引
    Rey(head)

}

运行结果

{node10 love9 0xc000078660}
{node9 love8 0xc000078630}
{node8 love7 0xc000078600}
{node7 love6 0xc0000785d0}
{node6 love5 0xc0000785a0}
{node5 love4 0xc000078570}
{node4 love3 0xc000078540}
{node3 love2 0xc000078510}
{node2 love1 0xc0000784b0}
{王五 123456 0xc0000784e0}
{node1 love0 0xc000078480}
{张三 love789 <nil>}

修改链表方案1

package main

import (
    "fmt"
)

//链表的增删改查
//首先定义结构体
type Head struct {
    User string
    pwd  string
    next *Head //链表
}

//头部添加

func AddHead(h **Head) {
    for i := 0; i < 10; i++ {
            var AddHead Head = Head{
                    User: fmt.Sprintf("node%d", i+1),
                    pwd:  fmt.Sprintf("love%d", i),
            }
            AddHead.next = *h
            *h = &AddHead
    }
}

//任意位置添加链表
func AddRandom(a *Head, n *Head) {
    for a != nil {
            if a.User == "node2" {

                    //切换next
                    n.next = a.next
                    a.next = n
            }
            a = a.next
    }
}
func UpdataHead(u *Head, name string, n *Head) {

    var up = u
    for u != nil {
            if u.User == name {
                    up.next = u.next
                    break
            }
            // up = u
            // u = u.next

            if u.User == name {
                    n.next = u.next
                    u.next = n
            }
            up = u
            u = u.next

    }
}

//遍历链表
func Rey(list *Head) {

    for list != nil {
            fmt.Println(*list)
            //让list变为下一结构体地址
            list = list.next
    }
}
func main() {

    //头部链表
    var head *Head = &Head{
            User: "张三",
            pwd:  "love789",
    }

    //定义一个中间连接的链表块
    var NewHead = &Head{
            User: "王五",
            pwd:  "123456",
    }
    //调用头部添加的链表
    AddHead(&head)

    //调用任意位置添加的链表
    AddRandom(head, NewHead)

    //修改
    UpdataHead(head, "node3", NewHead)
    //从头部索引
    Rey(head)

}

修改链表方案2

package main

import (
    "fmt"
)

//链表的增删改查
//首先定义结构体
type Head struct {
    User string
    pwd  string
    next *Head //链表
}


//头部添加

func AddHead(h **Head) {
    for i := 0; i < 10; i++ {
            var AddHead Head = Head{
                    User: fmt.Sprintf("node%d", i+1),
                    pwd:  fmt.Sprintf("love%d", i),
            }
            AddHead.next = *h
            *h = &AddHead
    }
}

//任意位置添加链表
func AddRandom(a *Head, n *Head) {
    for a != nil {
            if a.User == "node2" {

                    //切换next
                    n.next = a.next
                    a.next = n
            }
            a = a.next
    }
}

//修改链表
func modifyStudentNode(head *Head, name string, n *Head) {
    temp := head
    //思路:
    //1.找到要修改的结点的no,和temp.next.no作比较
    for temp != nil {
            if temp.next.User == name {
                    //说明我们已经找到这个要修改的结点了
                    head.next = temp.next

                    temp.next = n
                    break
            }
            temp = temp.next
            head = temp

    }

}
//遍历链表
func Rey(list *Head) {

    for list != nil {
            fmt.Println(*list)
            //让list变为下一结构体地址
            list = list.next
    }
}
func main() {

    //头部链表
    var head *Head = &Head{
            User: "张三",
            pwd:  "love789",
    }

    //定义一个中间连接的链表块
    var NewHead = &Head{
            User: "王五",
            pwd:  "123456",
    }

    //调用头部添加的链表
    AddHead(&head)

    //调用任意位置添加的链表
    AddRandom(head, NewHead)

    modifyStudentNode(head, "node2", NewHead)
    //从头部索引
    Rey(head)

}

修改结果
{node10 love9 0xc0000c2630}
{node9 love8 0xc0000c2600}
{node8 love7 0xc0000c25d0}
{node7 love6 0xc0000c25a0}
{node6 love5 0xc0000c2570}
{node5 love4 0xc0000c2540}
{node4 love3 0xc0000c2510}
{node3 love2 0xc0000c2480}
{王五 123456 0xc0000c24b0}
{node1 love0 0xc0000c2450}

删除链表

package main

import (
    "fmt"
)

//链表的增删改查
//首先定义结构体
type Head struct {
    User string
    pwd  string
    next *Head //链表
}


//头部添加

func AddHead(h **Head) {
    for i := 0; i < 10; i++ {
            var AddHead Head = Head{
                    User: fmt.Sprintf("node%d", i+1),
                    pwd:  fmt.Sprintf("love%d", i),
            }
            AddHead.next = *h
            *h = &AddHead
    }
}

//删除链表
func deleteHead(d *Head) {
    var del = d
    for d != nil {
            if d.User == "node5" {
                    del.next = d.next
                    break
            }
            del = d
            d = d.next
    }
}

//遍历链表
func Rey(list *Head) {

    for list != nil {
            fmt.Println(*list)
            //让list变为下一结构体地址
            list = list.next
    }
}
func main() {

    //头部链表
    var head *Head = &Head{
            User: "张三",
            pwd:  "love789",
    }

    //调用头部添加的链表
    AddHead(&head)

    //调用删除
    deleteHead(head)
    //从头部索引
    Rey(head)

}

运行结果

{node10 love9 0xc000078630}
{node9 love8 0xc000078600}
{node8 love7 0xc0000785d0}
{node7 love6 0xc0000785a0}
{node6 love5 0xc000078540}
{node4 love3 0xc000078510}
{node3 love2 0xc0000784e0}
{node2 love1 0xc0000784b0}
{node1 love0 0xc000078480}
{张三 love789 <nil>}

二叉树

满足以下两个条件的树就是二叉树:

1.本身是有序树;

2.树中包含的各个节点的度不能超过2,即只能是0、1或者2;

前序遍历二叉树——根左右

package main

import "fmt"
//定义结构体
type Student struct {

    Name  string
    Age int
    Score float32
    left *Student
    right*Student
}

/*二叉树*/
func main(){
    //根节点

    var root student
    root.Name = "root"
    root.Age = 10
    root. Score = 90

    //左子树
    var left1 student
    left1.Name = "left1"
    left1.Age = 20
    left1.Score = 80

    root.left = &left1
    //右子树
    var right1 student
    right1. Name = "right1”
    right1. Age = 30
    right1. Score - 70

    root.right - &right1

    //二级左子树

    var left2 Student
    left2.Name = "left2”
    left2.Age = 40

    left2.Score = 60

    left1.left = &left2

    //调用遍历函数
    Req(&root)
}
//递归算法遍历整颗二叉树
func Req(rootl *student){

    if root == nil {
        return
    }

    fmt.Println(root)
    //遍历左子树
    Req(root.left)
    //遍历右子树
    Req(root.right)
}

运行结果

&{root 10 90 exce880764be exce880764ee}
&{left1 28 80 exce88876510<nil>}
&{left2 40 60 <nil><nil>}
&{right1 30 70 <nil> <nil>}

中序遍历——左根右

func Req(rootl *student){
​
    if root == nil {
​
        return
}
​

    //遍历左子树
    Req(root.left)

    fmt.Println(root)
    //遍历右子树
    Req(root.right)
}

后序遍历——左右根

func Req(rootl *student){
​
    if root == nil {
​
        return
}
​

    //遍历左子树
    Req(root.left)

​
    //遍历右子树
    Req(root.right)

    fmt.Println(root)
}