GO结构体链表及二叉树

目录

存储方式

链表更新

  链表实现增删改查

        头部添加链表 

      尾添加链表

          从中间任意添加链表

         修改链表(1-2)

        2、

修改结果

        删除链表

二叉树

                前序遍历

                中序遍历——左根右

                后序遍历——左右根


      

  链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。

        链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。

        使用链表结构可以避免在使用数组时需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。
        
        链表允许插入和移除表上任意位置上的结点,但是不允许随机存取。链表有三种类型:单向链表、双向链表以及循环链表。

 

        结构体是自定义复杂数据结构,struct里面可以包含多个字段(属性),struct类型到可以定义方法,和函数有区分,struct属于值类型,且可以做嵌套,Go中没有Class类型,只有struct类型。

struct定义的三种形式:其中2和3都是返回结构体的指针。

1: var stu Student
2: var stu *Student = new (Student)
3: var stu *Student = &Student {} 

存储方式

        值类型存储方式地址空间连续  

示例

package main

import "fmt"

type Student struct {
	Name  string
	Age   int32
	Score float32
}

func main() {
	var stu *Student = &Student{

		Name: "zhangsan",

		Age: 18,

		Score: 90,
	}

	fmt.Printf("Name :%p\n", &stu.Name)
	fmt.Printf("Age :%p\n", &stu.Age)
	fmt.Printf("Score:%p\n", &stu.Score)
}



运行结果

Name :0xc000004078
Age :0xc000004088
Score:0xc00000408c

        利用 Struct 可以包容多种数据类型的特性,使用它作为链表的结点是最合适不过了。一个结构体内可以包含若干成员,这些成员可以是基本类型、自定义类型、数组类型,也可以是指针类型。这里可以使用指针类型成员来存放下一个结点的地址。

使用 Struct 定义一个单向链表。

type Node struct {

    Data int
    Next *node
}

链表更新

package main

import "fmt"

type Student struct {
	Name string
	age  int
	city string
	next *Student
}

func main() {

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

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

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

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

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

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

}
func Rey(a *Student) {

	//遍历输出链表中每一个结构体
	for a != nil {
		fmt.Println(*a)

		a = a.next
	}

}

结果

{zhangsan 20 nj 0xc0000784b0}
{lisi 22 wh 0xc0000784e0}
{wangwu 26 wh <nil>}

  链表实现增删改查

        头部添加链表 

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 Rey(list *Head) {

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

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


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

}

运行结果

{node10 love9 0xc0000c2600}
{node9 love8 0xc0000c25d0}
{node8 love7 0xc0000c25a0}
{node7 love6 0xc0000c2570}
{node6 love5 0xc0000c2540}
{node5 love4 0xc0000c2510}
{node4 love3 0xc0000c24e0}
{node3 love2 0xc0000c24b0}
{node2 love1 0xc0000c2480}
{node1 love0 0xc0000c2450}
{张三 love789 <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-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 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}
{张三 love789 <nil>}

        删除链表

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)
}
​

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小柏ぁ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值