r1笔记第12天 Golang(12)

这篇笔记探讨了在Golang中如何进行链表的尾部插入操作,强调了指针在链表操作中的重要性。通过示例解释了在for循环中使用指针变量与变量的区别,并通过图解分析了传递指针与指针地址的区别。同时,提到了生活中的一些琐事,如天气、拼多多活动、即将到来的菲律宾出差等。
摘要由CSDN通过智能技术生成

链表的尾部插入:先定义一个入口,接着批量插入。

单向链表,需要先定义一个入口,然后定义一个临时指针变量,存储这个入口的地址,利用for循环,指针变量作为节点临时存储的中间值,同时,指针变量的next指向下一个节点的地址。

多加了个%T查看类型,%p查看具体的地址,发现,程序会先把内存申请好,然后才开始工作。另外,内存结构确实是一个接着一个的。

for循环中,变量操作与地址操作 var stu = Student{}  也可以换成 stu := &Student ,直接操作地址。

package main

import (
	"fmt"
	"math/rand"
	"time"
)

type Student struct{
	Name string
	Age  int
	Score float32
	Next* Student
}

func trans( p *Student)  {
	for p.Next != nil{
		fmt.Println(*p)
		p = p.Next
		time.Sleep(1*time.Second)
	} 
	fmt.Println(*p)
}

func main()  {
	var head Student

	var tail = &head
	fmt.Printf("start: %T, %p\n",tail.Next,tail.Next)
	for i:=0;i<10;i++{
		var stu = Student {
			Name: fmt.Sprintf("stu%d",i),
			Age:  rand.Intn(100),
			Score: rand.Float32()*100, 
		}
		tail.Next = &stu
		fmt.Printf("body: %T,%p\n",tail,tail)
		tail = &stu		
	}
	fmt.Printf("end: %T,%p\n",tail.Next,tail.Next)
	trans(&head)
}

运行结果:

PS F:\go\src\go_dev> .\main.exe
start: *main.Student, 0x0
body: *main.Student,0xc04207e210
body: *main.Student,0xc04207e240
body: *main.Student,0xc04207e270
body: *main.Student,0xc04207e2a0
body: *main.Student,0xc04207e2d0
body: *main.Student,0xc04207e300
body: *main.Student,0xc04207e330
body: *main.Student,0xc04207e360
body: *main.Student,0xc04207e390
body: *main.Student,0xc04207e3c0
end: *main.Student,0x0
{ 0 0 0xc04207e240}
{stu0 81 94.05091 0xc04207e270}
{stu1 47 43.77142 0xc04207e2a0}
{stu2 81 68.682304 0xc04207e2d0}
{stu3 25 15.651925 0xc04207e300}
{stu4 56 30.091187 0xc04207e330}
{stu5 94 81.36399 0xc04207e360}
{stu6 62 38.06572 0xc04207e390}
{stu7 28 46.888985 0xc04207e3c0}
{stu8 11 29.310184 0xc04207e3f0}
{stu9 37 21.855305 <nil>}
PS F:\go\src\go_dev>

 


头部插入:知道最后一个节点,新的节点的指针指最后一个,不断往前迭代。用变量的话,是值拷贝,用指针试试,指向地址不一样,就不会出现重复赋值。(最好先画图,涉及到指针时候,要分清改变的是指针还是指针的地址,这里是个隐患)

如果要改变变量指针的地址,就传入变量的地址

如果要改变指针指针的地址,就传入指针变量的地址

package main

import (
	"fmt"
	"math/rand"
	"time"
)

type Student struct{
	Name string
	Age  int
	Score float32
	Next* Student
}

func trans( p *Student)  {
	for p.Next != nil{
		fmt.Println(*p)
		p = p.Next
		time.Sleep(1*time.Second)
	} 
	fmt.Println(*p)
}

func insertHead(p **Student)  {
	for i := 0;i<10; i++ {
		var stu = Student{
			Name: fmt.Sprintf("stu%d",i),
			Age:  rand.Intn(100),
			Score: rand.Float32()*100, 
		}
		stu.Next = *p
		//p = &stu  调用指针的副本,这里是个坑
		*p = &stu
	}
}


func main()  {	
	fmt.Println("insert head")
	var tail *Student = new(Student)
	/*
	for i := 0;i<10; i++ {
		var stu = Student{
			Name: fmt.Sprintf("stu%d",i),
			Age:  rand.Intn(100),
			Score: rand.Float32()*100, 
		}
		stu.Next = tail
		tail = &stu
	}
	*/
	insertHead(&tail)
	trans(tail)
}

运行结果:

PS F:\go\src\go_dev> .\main.exe
insert head
{stu9 85 30.152267 0xc0420726c0}
{stu8 37 5.912065 0xc042072690}
{stu7 29 7.9453626 0xc042072660}
{stu6 87 60.72534 0xc042072630}
{stu5 41 2.8303082 0xc042072600}
{stu4 90 69.67192 0xc0420725d0}
{stu3 87 20.658266 0xc0420725a0}
{stu2 47 29.708258 0xc042072570}
{stu1 28 86.249146 0xc042072540}
{stu0 95 36.08714 0xc042072510}
{ 0 0 <nil>}
PS F:\go\src\go_dev>

解析一下:这个例子很经典:

//需要改变指针指向的地址,因为函数的参数是一个值拷贝,也就是副本,指针也是一个副本,形参改变,不会改变外面的实参。 也就是说,只有用传地址进去,才能改变外面实参的值。
func insertHead(p **Student)  {
	for i := 0;i<10; i++ {
		var stu = Student{
			Name: fmt.Sprintf("stu%d",i),
			Age:  rand.Intn(100),
			Score: rand.Float32()*100, 
		}
		stu.Next = *p
		//p = &stu  调用指针的副本,这里是个坑,如果不传入指针的地址,那么改变的只是副本的值。
		*p = &stu
	}
}

//这里需要将指针的地址传进去
func main()  {
	fmt.Println("insert head")
	var tail *Student = new(Student)
	insertHead(&tail)
	trans(tail)
}

图解来看是这样的: head是指针,func传入指针的值,那就会生成一个副本,变成head1,修改head1的值,不会影响head指向的地址,如果要改变head,就需要用指针的指针,传入指针的地址,修改head1,才能改变head的值。


2019年12月12日 今天天气特别好。

昨晚加湿器没水,睡到后半夜太干燥,今天喉咙出问题了,有点难受。

今天拼多多的活动,通过小伙伴的努力,攒到了200元,真棒~ 和大家平分,结果小伙伴们有的没拿,改天弥补他们。

嗯,双十二了,买条内存,升级一下电脑。

菲律宾出差的事情有消息了,可能月底就要出发,有点不舍,因为刚刚熟悉一个地方,又要离开。这次出差结束,回来应该会常驻这边,也挺好的,小伙伴说,明年春暖花开的时候,一起去爬山~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值