Golang 链表的创建和读取 小记

文章目录

链表的相关知识

  链表有时会具有头节点,头节点的指针指向第一个节点的地址,其本身的数据域可以根据自己的选择进行赋值

  接下来我将以将int转换为链表为例进行演示,如果有什么地方可以改进,也希望路过大神能够指出

链表的创建:

链表的结构定义一般如下,即由本身的数据和指向下一个节点的指针构成

go 复制代码
type ListNode struct {
	Val  int
	Next *ListNode//不能直接赋值listnode,避免产生嵌套引用
}

  链表的创建(每个节点存储一位数字),在创建的过程中 我们需要设置中间的可变节点,不然我们可能会丢失对链表的第一个节点的索引,以下的例子中我们就使用middle为中间节点;将head设置为头节点,并代表完整的链表

模拟方式建立

  我们利用迭代的方法,只要还存在num,就更新创建一个新的节点

go 复制代码
// 尝试建立有头节点的链表,关键在于赋值给middle.next
func CreateList(nums int) *ListNode {
	Head := new(ListNode) //这代表一整个链表,并通过这里的头节点进行标注,方便该链表的引用

	middle := Head //middle视作Head链表的中间节点,其一直改变

	for nums > 0 {
		middle.Next = &ListNode{Val: nums % 10}//头节点赋值方法
		fmt.Printf("middle.Val: %v\n", middle.Val)
		middle = middle.Next
		nums /= 10
	}
	return Head
}

链表的递归创建

go 复制代码
// 递归建立链表
func RecurCreateList(nums int) *ListNode {
	//在递归时好像不需要单独保存头节点位置,后续的位置会递归存储在next中,不用考虑被覆盖的问题
	middle := new(ListNode) //建立头指针,其指针不变

	// 123%10=3
	// 12.3%10=2
	// 1.23%10=1

	// 120%10=0
	// 12 %10=2
	// 1.2%10=1

	if nums > 1 || nums%10 > 0 {
		middle.Val = nums % 10
		fmt.Printf("middle.Val: %v\n", middle.Val)

		if nums > 1 {
			nums /= 10
			middle.Next = RecurCreateList(nums)
		}

	}
	return middle
}

链表的读取

遍历读取

  链表读取时我们需要根据是否具有头节点进行一定的调整,下面是使用遍历(迭代)进行创建的过程

go 复制代码
// 尝试遍历读取链表
func ReadList(L ListNode) {
	middle := L //将头节点赋予这里的中间节点middle

	//循环读取链表的内容
	for middle.Next != nil {
		v := middle.Next.Val //由于我们这里判断的是本身节点是否为空,所以在输出时使用下一节点的值进行输出,避免错过某个值
		fmt.Printf("v: %v\n", v)
		// 	// fmt.Printf("L: %v\n", L)
		middle = *middle.Next
		// 	// fmt.Printf("L: %v\n", L)
	}
}

递归读取

下面为使用递归 进行读取的方法

由于节点的定义过程中使用内嵌,在建立相关函数时都使用指针比较方便 虽然前面都没注意:( ,

go 复制代码
// 尝试递归读取链表
func RecurReadList(L *ListNode) {

	fmt.Printf("L.Val: %v\n", L.Val) //打印出此节点中的Val

	//如果本结点的指针不为空,即还有下一个节点,继续读取
	if L.Next != nil {
		RecurReadList(L.Next) //将下个节点的指针传入
	}
	//如果运行到这里,说明指针为空,函数也就到此结束了
}

完整代码

go 复制代码
package main

import (
	"fmt"
)

type ListNode struct {
	Val  int
	Next *ListNode
}

func main() {
	// l := CreateList(13)
	l := RecurCreateList(13)
	fmt.Printf("l: %v\n", *l)
	// ReadList(*l)
	RecurReadList(l)
	// RecurReadList(l.Next)
	// fmt.Println(l.Next.Val)
}

// 尝试建立有头节点的链表,关键在于赋值给middle.next
func CreateList(nums int) *ListNode {
	Head := new(ListNode) //这代表一整个链表,并通过这里的头节点进行标注,方便该链表的引用

	middle := Head //middle视作Head链表的中间节点,其一直改变

	for nums > 0 {
		middle.Next = &ListNode{Val: nums % 10} //头节点赋值方法
		fmt.Printf("middle.Val: %v\n", middle.Val)
		middle = middle.Next
		nums /= 10
	}
	return Head
}

// 递归建立链表
func RecurCreateList(nums int) *ListNode {
	//在递归时好像不需要单独保存头节点位置,后续的位置会递归存储在next中,不用考虑被覆盖的问题
	middle := new(ListNode) //建立头指针,其指针不变

	// 123%10=3
	// 12.3%10=2
	// 1.23%10=1

	// 120%10=0
	// 12 %10=2
	// 1.2%10=1

	if nums > 1 || nums%10 > 0 {
		middle.Val = nums % 10
		fmt.Printf("middle.Val: %v\n", middle.Val)

		if nums > 1 {
			nums /= 10
			middle.Next = RecurCreateList(nums)
		}

	}
	return middle
}

// 尝试遍历读取链表
func ReadList(L ListNode) {

	middle := L //将头节点赋予这里的中间节点middle

	//循环读取链表的内容
	for middle.Next != nil {
		v := middle.Next.Val //由于我们这里判断的是本身节点是否为空,所以在输出时使用下一节点的值进行输出,避免错过某个值
		fmt.Printf("v: %v\n", v)
		// 	// fmt.Printf("L: %v\n", L)
		middle = *middle.Next
		// 	// fmt.Printf("L: %v\n", L)
	}
}

// 尝试递归读取链表
func RecurReadList(L *ListNode) {

	fmt.Printf("L.Val: %v\n", L.Val) //打印出此节点中的Val

	//如果本结点的指针不为空,即还有下一个节点,继续读取
	if L.Next != nil {
		RecurReadList(L.Next) //将下个节点的指针传入
	}
	//如果运行到这里,说明指针为空,函数也就到此结束了
}
相关推荐
码智社36 分钟前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海38 分钟前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖2 小时前
JDK 26 新特性详解
java·开发语言
马优晨2 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
a1117763 小时前
2FA 验证码生成器(github登录验证 app)
笔记·学习
我的xiaodoujiao4 小时前
API 接口自动化测试详细图文教程学习系列32--Allure测试报告2
python·学习·测试工具·pytest
人邮异步社区4 小时前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大4 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai5 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
এ慕ོ冬℘゜5 小时前
前端基础:什么是时间戳?JS获取时间戳三种方法与实战用途
开发语言·前端·javascript