当前位置: 首页 > news >正文

单链表在Go语言中的实现与操作

简介

单链表是一种基本的线性数据结构,由节点组成,每个节点存储数据和指向下一个节点的指针。今天,我们将深入探讨如何在Go语言中实现和操作单链表。

单链表的优缺点

  • 优点

    • 动态内存分配,灵活性高。
    • 插入和删除节点操作在时间复杂度上比数组更优。
  • 缺点

    • 访问元素需要顺序遍历,时间复杂度为O(n)。
    • 占用额外的内存来存储指针。

代码实现

下面是我们在Go中实现单链表的完整代码:

// -------------------------------------------
// @file      : SingleLinkedList.go
// @author    : Serein
// @contact   : xming9523@gmail.com
// @blog      : https://blog.childish.vip
// @time      : 2024/12/3 20:33:32 星期二
// -------------------------------------------package mainimport "fmt"// 单链表// ListNode 节点结构体定义
type ListNode struct {Val  int       // 节点的值Next *ListNode // 指向下一个节点的指针
}// SingleLinkedList 单链表结构体定义
type SingleLinkedList struct {Head *ListNode // 链表的头节点Tail *ListNode // 链表的尾节点
}// NewSingleLinkedList 初始化单链表函数
func NewSingleLinkedList() *SingleLinkedList {// 初始化时,链表为空return &SingleLinkedList{Head: nil, Tail: nil}
}// insertNode 插入节点的通用方法
func (l *SingleLinkedList) insertNode(val int, atHead bool) {newNode := &ListNode{Val: val} // 创建一个新节点// 如果链表为空if l.Head == nil {l.Head = newNodel.Tail = newNode // 头部和尾部都指向新节点return}// 如果要在头部插入if atHead {newNode.Next = l.Head // 新节点的 Next 指向源头部节点l.Head = newNode      // 跟新头部节点} else {// 如果要在尾部插入l.Tail.Next = newNode // 当前尾节点的 Next 指向新节点l.Tail = newNode      // 更新尾节点}
}// InsertAtHead 在头部插入节点操作
func (l *SingleLinkedList) InsertAtHead(val int) {l.insertNode(val, true) // 调用insertNode,在头部插入
}// 在尾部插入节点操作
func (l *SingleLinkedList) InsertAtTail(val int) {l.insertNode(val, false) // 调用insertNode,在尾部插入
}// InsertAtRandomPosition 在指定位置插入节点
func (l *SingleLinkedList) InsertAtRandomPosition(pos int, val int) {// 如果位置小于等于0或者链表为空,则插入头部if pos <= 0 || l.Head == nil {l.InsertAtHead(val) // 直接在头部插入return}// 计算链表长度length := 0current := l.Headfor current != nil {length++current = current.Next}// 如果位置超出链表的长度,就在尾部插入if pos >= length {l.InsertAtTail(val) // 在尾部插入return}// 遍历链表,找到指定位置的前一个位置current = l.Headfor i := 0; i < pos-1; i++ {current = current.Next // 移动到目标位置的前一个节点}// 在执行位置插入节点newNode := &ListNode{Val: val}newNode.Next = current.Next // 新节点的 Next 指向原来的节点current.Next = newNode      // 将原位置的节点的 Next 指向新节点}func (l *SingleLinkedList) DeleteAtPosition(pos int) {// 如果链表为空或删除位置无效,直接返回if l.Head == nil || pos < 0 {return}// 如果删除的是头节点if pos == 0 {l.Head = l.Head.Next // 新节点更新为原头节点的下一个位置if l.Head == nil {l.Tail = nil // 如果删除后链表为空,则尾节点也置空}return}// 初始化当前节点为头节点current := l.Headfor i := 0; current != nil && i < pos-1; i++ {current = current.Next // 移动到要删除节点的前一个节点去}// 如果当前节点为空,说明位置超出了链表的范围,直接返回if current == nil || current.Next == nil {return}// 如果删除的是尾节点if current.Next == l.Tail {l.Tail = current // 更新尾节点}// 删除当前节点的下一个节点current.Next = current.Next.Next}// 打印单链表操作
func (l *SingleLinkedList) PrintList() {current := l.Headfor current != nil {fmt.Println(current.Val)current = current.Next}}func main() {singList := NewSingleLinkedList()singList.InsertAtHead(2)singList.InsertAtTail(3)singList.InsertAtHead(1)singList.InsertAtRandomPosition(2, 4)singList.PrintList()singList.DeleteAtPosition(2)fmt.Println("删除2节点后")singList.PrintList()}

关键点解析

  • 节点结构体ListNode定义了节点的结构,包含数据Val和指向下一个节点的指针Next
  • 链表结构体SingleLinkedListHeadTail指针来管理链表,这简化了对头部和尾部的操作。
  • 初始化NewSingleLinkedList函数返回一个空的单链表。
  • 插入操作
    • InsertAtHeadInsertAtTail方法简化了在头部或尾部插入新节点的操作。
    • InsertAtRandomPosition允许我们在链表的指定位置插入节点。
  • 删除操作DeleteAtPosition展示了如何删除指定位置的节点,并处理了特殊情况,如删除头节点或尾节点。
  • 打印链表PrintList方法遍历并打印链表中的每个节点值。

运行和测试

main函数中,我们展示了如何创建一个单链表,插入节点,删除节点并打印链表的状态:

func main() {// ... (代码)
}

总结

通过这个实现,我们学习了如何在Go中构建和操作一个单链表。尽管单链表在某些方面比数组或双向链表更受限制,但在内存效率和操作简便性上,它仍然是一个有价值的数据结构。Go语言的简单语法使得这些操作变得直观而高效。

实际应用

  • 缓存机制:单链表可以实现LRU(最近最少使用)缓存。
  • 任务队列:在事件驱动的系统中,任务可以按顺序存储在单链表中。
  • 符号表:在编译器设计中,单链表用于实现符号表。

相关文章:

单链表在Go语言中的实现与操作

简介 单链表是一种基本的线性数据结构&#xff0c;由节点组成&#xff0c;每个节点存储数据和指向下一个节点的指针。今天&#xff0c;我们将深入探讨如何在Go语言中实现和操作单链表。 单链表的优缺点 优点&#xff1a; 动态内存分配&#xff0c;灵活性高。插入和删除节点操…...

网关整合sentinel无法读取nacos配置问题分析

sentinel无法读取nacos配置问题分析 1.spring-cloud-gateway整合sentinel2.问题现象3.原因猜测4.源码分析4. 结语 最近公司需要上线一个集约项目&#xff0c;虽然为内网项目&#xff0c;但曾经有过内网被攻破&#xff0c;导致内部系统被攻击的案例&#xff0c;且集约系统同时在…...

简化XPath表达式的方法与实践

XPath表达式用于在XML或HTML文档中定位元素。有时候&#xff0c;XPath表达式可能会变得非常冗长和复杂&#xff0c;这不仅难以阅读和维护&#xff0c;而且也可能影响性能。因此&#xff0c;学会如何简化XPath表达式是非常重要的。本文将介绍几种简化XPath表达式的方法&#xff…...

【文件下载】接口传递文件成功和失败时,前端的处理方式

问题 使用bold类型从后端接口获取文件流&#xff0c;获取成功的时候通过a标签下载&#xff1b;失败的时候&#xff0c;后端返回的是json&#xff0c;这个时候就无法向用户展示后端返回的错误提示信息。 思路 根据返回类型是否为 application/json 区分是否返回成功&#xff…...

html+css网页设计马林旅行社移动端4个页面

htmlcss网页设计马林旅行社移动端4个页面 网页作品代码简单&#xff0c;可使用任意HTML辑软件&#xff08;如&#xff1a;Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作&#xff09;。 获取源码 1&#…...

视频 的 音频通道提取 以及 视频转URL 的在线工具!

视频 的 音频通道提取 以及 视频转URL 的在线工具&#xff01; 工具地址: https://www.lingyuzhao.top/toolsPage/VideoTo.html 它提供了便捷的方法来处理视频文件&#xff0c;具体来说是帮助用户从视频中提取音频轨道&#xff0c;并将视频转换为可以通过网络访问的URL链接。无…...

容易被遗忘的测试用例

网络服务器启动了吗&#xff1f;应用程序服务器启动了吗&#xff1f;数据库上线了吗&#xff1f;测试数据是否预先加载到数据库中&#xff1f;每当我们准备开始测试应用程序时&#xff0c;一切都应该已经准备妥当。 然而&#xff0c;当测试开始后&#xff0c;我们可能会漏掉一些…...

uni-app写的微信小程序如何实现账号密码登录后获取token,并且每天的第一次登录后都会直接获取参数而不是耀重新登录(2)

接uni-app写的微信小程序如何实现账号密码登录后获取token&#xff0c;并且每天的第一次登录后都会直接获取参数而不是耀重新登录&#xff08;1&#xff09;&#xff0c; 在main.js中 import App from ./App// #ifndef VUE3 import Vue from vue import ./uni.promisify.adap…...

统计中间件稳定性指标

目前订单业务域涉及中间件&#xff1a;MySQL、Redis、TiDB、MQ、ES。&#xff08;遗漏项请补充&#xff09; 一、RDS 资源使用率 实例ID实例名称规格maxCPUavgCPUmaxDISKmaxIOPSavgIOPS活跃会话maxTPSavgTPSmaxQPSavgQPS实例风险 慢查询 慢查询会消耗大量的系统资源&#x…...

移动端使用REM插件postcss之postcss-px2rem

目录 一、概念 二、核心特性 三、功能 四、插件模块 注意事项&#xff1a; 五、使用 安装&#xff1a; 配置 一、概念 工具类型&#xff1a;PostCSS是一个基于JavaScript的工具&#xff0c;用于转换CSS的工作流。核心理念&#xff1a;PostCSS的核心理念是“转换而非替…...

FPGA Xilinx维特比译码器实现卷积码译码

FPGA Xilinx维特比译码器实现卷积码译码 文章目录 FPGA Xilinx维特比译码器实现卷积码译码1 Xilinx维特比译码器实现2 完整代码3 仿真结果 MATLAB &#xff08;n,k,m&#xff09;卷积码原理及仿真代码&#xff08;你值得拥有&#xff09;_matlab仿真后代码-CSDN博客 MATLAB 仿真…...

hive 行转列

行转列的常规做法是&#xff0c;group bysum(if())【或count(if())】 建表: CREATE TABLE table2 (year INT,month INT,amount DOUBLE );INSERT INTO table2 (year, month, amount) VALUES(1991, 2, 1.2),(1991, 3, 1.3),(1991, 4, 1.4),(1992, 1, 2.1),(1992, 2, 2.2),(1992…...

Vue中使用ECharts图表中的阈值标记(附源码)

在数据处理和可视化领域&#xff0c;我们经常需要对一系列数据点进行分析。本文将介绍如何在给定的数据点中找到对应于特定Y值的X值&#xff0c;并设置标线起始点标记在ECharts图表中&#xff0c;效果图如下&#xff1a; 实现步骤 1、数据准备 let seriesData [// 提供日期…...

【特征融合】融合空间域和频率域提升边缘检测能力

基于深度学习的边缘检测方法已显示出巨大的优势,并获得了可喜的性能。然而,目前大多数方法只能从空间(RGB)域提取特征进行边缘检测,可挖掘的信息有限。因此,这些方法无法很好地应用于物体与背景颜色相似的场景。为了应对这一挑战,提出了一种融合空间域和频率域特征的新型…...

深入理解AVL树:结构、旋转及C++实现

1. AVL树的概念 什么是AVL树&#xff1f; AVL树是一种自平衡的二叉搜索树&#xff0c;其发明者是Adelson-Velsky和Landis&#xff0c;因此得名“AVL”。AVL树是首个自平衡二叉搜索树&#xff0c;通过对树的平衡因子进行控制&#xff0c;确保任何节点的左右子树高度差最多为1&…...

AUTOSAR AP 汽车API知识点总结(Automotive API )R24-11

汽车API知识点总结 一、背景与目标 背景:智能互联汽车正逐步依赖远程诊断、软件更新等功能以确保行驶安全,并且用户已习惯于通过智能设备中的应用程序控制连接设备。虽然AUTOSAR标准支持车辆软件的可更新性,但尚未提供将AUTOSAR应用产生的数据和功能安全可靠地暴露给非AUTO…...

【HarmonyOS开发】超详细的ArkTS入门

安装DevEco Studio和新建项目就不多说了&#xff0c;可以移步官网 就可以把他们拆成这几个部分了&#xff0c;如果看不懂可以暂时忽略下面冒号后面的内容 装饰器&#xff1a;用于装饰类、结构、方法以及变量&#xff0c;并赋予其特殊的含义。如上述示例中Entry、Component和St…...

Springboot(五十一)SpringBoot3整合Sentinel-nacos持久化策略

上文中我记录了在Springboot项目中链接sentinel-dashboard使用限流规则的全过程。 但是呢,有一个小小的问题,我重启了一下我本地的sentinel-dashboard服务,然后,我之前创建的所有的流控规则都没了…… 这……好像有点不合理啊,咱就不能找地儿存储一下?你这一重启就没了,…...

[go-redis]客户端的创建与配置说明

创建redis client 使用go-redis库进行创建redis客户端比较简单&#xff0c;只需要调用redis.NewClient接口创建一个客户端 redis.NewClient(&redis.Options{Addr: "127.0.0.1:6379",Password: "",DB: 0, })NewClient接口只接收一个参数red…...

Qt入门7——Qt事件

目录 1. Qt事件介绍&#xff1a; 2. 事件的处理 示例1&#xff1a;鼠标进入(enterEvent)与离开事件(leaveEvent) 示例2&#xff1a;鼠标点击事件(mousePressEvent) 示例3&#xff1a;鼠标移动事件(mouseMoveEvent) 3. 按键事件 4. 定时器 5. 窗口事件 1. Qt事件介绍&a…...

挑战杯推荐项目

“人工智能”创意赛 - 智能艺术创作助手&#xff1a;借助大模型技术&#xff0c;开发能根据用户输入的主题、风格等要求&#xff0c;生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用&#xff0c;帮助艺术家和创意爱好者激发创意、提高创作效率。 ​ - 个性化梦境…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

大数据零基础学习day1之环境准备和大数据初步理解

学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 &#xff08;1&#xff09;设置网关 打开VMware虚拟机&#xff0c;点击编辑…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入&#xff0c;一个是通过INMP441麦克风模块采集音频&#xff0c;一个是通过PCM5102A模块播放音频&#xff0c;那如果我们将两者结合起来&#xff0c;将麦克风采集到的音频通过PCM5102A播放&#xff0c;是不是就可以做一个扩音器了呢…...

基于matlab策略迭代和值迭代法的动态规划

经典的基于策略迭代和值迭代法的动态规划matlab代码&#xff0c;实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...

并发编程 - go版

1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程&#xff0c;系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...

Python Einops库:深度学习中的张量操作革命

Einops&#xff08;爱因斯坦操作库&#xff09;就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库&#xff0c;用类似自然语言的表达式替代了晦涩的API调用&#xff0c;彻底改变了深度学习工程…...

django blank 与 null的区别

1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是&#xff0c;要注意以下几点&#xff1a; Django的表单验证与null无关&#xff1a;null参数控制的是数据库层面字段是否可以为NULL&#xff0c;而blank参数控制的是Django表单验证时字…...

OD 算法题 B卷【正整数到Excel编号之间的转换】

文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的&#xff1a;a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...

【Linux】自动化构建-Make/Makefile

前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具&#xff1a;make/makfile 1.背景 在一个工程中源文件不计其数&#xff0c;其按类型、功能、模块分别放在若干个目录中&#xff0c;mak…...