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) //将下个节点的指针传入
	}
	//如果运行到这里,说明指针为空,函数也就到此结束了
}
相关推荐
蓝婷儿8 分钟前
6个月Python学习计划 Day 16 - 面向对象编程(OOP)基础
开发语言·python·学习
孔令飞20 分钟前
Kubernetes 节点自动伸缩(Cluster Autoscaler)原理与实践
ai·云原生·容器·golang·kubernetes
渣渣盟24 分钟前
基于Scala实现Flink的三种基本时间窗口操作
开发语言·flink·scala
叶子20242229 分钟前
学习使用YOLO的predict函数使用
人工智能·学习·yolo
jackson凌32 分钟前
【Java学习笔记】SringBuffer类(重点)
java·笔记·学习
chao_78934 分钟前
链表题解——两两交换链表中的节点【LeetCode】
数据结构·python·leetcode·链表
糯米导航1 小时前
Java毕业设计:办公自动化系统的设计与实现
java·开发语言·课程设计
糯米导航1 小时前
Java毕业设计:WML信息查询与后端信息发布系统开发
java·开发语言·课程设计
MessiGo1 小时前
Javascript 编程基础(5)面向对象 | 5.1、构造函数实例化对象
开发语言·javascript·原型模式
大霞上仙1 小时前
nonlocal 与global关键字
开发语言·python