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

Go语言中的链表与双向链表实现

链表基础

链表是一种由有限元素组成的数据结构,其中每个元素至少使用两个内存空间:一个存储实际数据,另一个存储指向下一个元素的指针,从而形成一个元素序列构成链表。链表的第一个元素称为头结点,而最后一个元素通常被称为尾结点。为了操作链表,保持对头结点的引用非常重要,因为头结点是我们访问整个链表的唯一入口。如果丢失了指向头结点的指针,将无法再次找到链表的其他元素。

链表的操作

在链表中,移除节点时,主要操作是调整要删除节点的前一个节点的指针,使其指向要删除节点的下一个节点。

Go中的链表实现

我们通过Go语言的链表实现来更好地理解链表的操作过程。

package mainimport ("fmt"
)// 定义链表节点结构
type Node struct {Value intNext  *Node
}// 全局变量root,保存链表的头结点
var root = new(Node)

在以上代码中,定义了链表节点的结构,包含一个Value用于存储节点的值,一个Next指针指向链表的下一个节点。此外,还定义了一个全局变量root,用于保存链表的头结点。

添加节点

链表通常不允许重复元素,并且当链表未排序时,新节点通常添加到链表末尾。以下是添加节点的代码实现:

func addNode(t *Node, v int) int {if root == nil {t = &Node{v, nil}root = treturn 0}if v == t.Value {fmt.Println("节点已存在:", v)return -1}if t.Next == nil {t.Next = &Node{v, nil}return -2}return addNode(t.Next, v)
}

addNode函数中,首先检查链表是否为空,如果为空,则将新节点作为头结点插入。接着,检查链表中是否已有待插入的值,避免重复元素。如果当前节点的Next指针为空,说明已到达链表末尾,便将新节点添加到链表的末尾。若以上情况均不满足,则递归地继续检查下一个节点。

遍历链表

遍历链表的代码如下:

func traverse(t *Node) {if t == nil {fmt.Println("-> 空链表!")return}for t != nil {fmt.Printf("%d -> ", t.Value)t = t.Next}fmt.Println()
}

traverse函数通过循环遍历链表,并输出每个节点的值,直到遍历到最后一个节点。

查找节点与计算链表长度

func lookupNode(t *Node, v int) bool {if root == nil {t = &Node{v, nil}root = treturn false}if v == t.Value {return true}if t.Next == nil {return false}return lookupNode(t.Next, v)
}func size(t *Node) int {if t == nil {fmt.Println("-> 空链表!")return 0}i := 0for t != nil {i++t = t.Next}return i
}

lookupNode用于检查链表中是否存在某个值,而size函数用于计算链表的长度,即节点的数量。通过递归或循环,分别遍历链表的每个节点,返回结果。

主函数测试

func main() {fmt.Println(root)root = niltraverse(root)addNode(root, 1)addNode(root, -1)traverse(root)addNode(root, 10)addNode(root, 5)addNode(root, 45)traverse(root)if lookupNode(root, 100) {fmt.Println("节点存在!")} else {fmt.Println("节点不存在!")}fmt.Println("链表长度:", size(root))
}

输出结果:

&{0 <nil>}
-> 空链表!
1 -> -1 ->
1 -> -1 -> 10 -> 5 -> 45 ->
节点不存在!
链表长度: 5

链表的优势

链表的优势在于其灵活性和实现的简单性,适合处理各种数据类型。链表在进行顺序查找时效率较高,特别是在动态数据管理(如插入和删除)时优于数组等静态数据结构。此外,链表可以动态增长,且删除节点的操作较为简单,尤其是有序链表。

双向链表

双向链表是一种特殊的链表结构,每个节点不仅有一个指向下一个节点的指针,还有一个指向前一个节点的指针。这样可以实现双向遍历。双向链表的头节点的前一个节点为nil,尾节点的下一个节点也为nil

Go中的双向链表实现

双向链表的节点定义如下:

type Node struct {Value    intPrevious *NodeNext     *Node
}

该结构体中有两个指针字段:一个指向前一个节点,一个指向下一个节点。

添加节点

func addNode(t *Node, v int) int {if root == nil {t = &Node{v, nil, nil}root = treturn 0}if v == t.Value {fmt.Println("节点已存在:", v)return -1}if t.Next == nil {temp := tt.Next = &Node{v, temp, nil}return -2}return addNode(t.Next, v)
}

与单链表类似,双向链表的节点通常添加到链表末尾。

遍历与反向遍历

func traverse(t *Node) {if t == nil {fmt.Println("-> 空链表!")return}for t != nil {fmt.Printf("%d -> ", t.Value)t = t.Next}fmt.Println()
}func reverse(t *Node) {if t == nil {fmt.Println("-> 空链表!")return}temp := tfor t != nil {temp = tt = t.Next}for temp.Previous != nil {fmt.Printf("%d -> ", temp.Value)temp = temp.Previous}fmt.Printf("%d -> ", temp.Value)fmt.Println()
}

reverse函数实现了反向遍历,先遍历到链表末尾,再通过Previous指针反向输出节点值。

双向链表的优势

双向链表相比单链表,优势在于可以进行双向遍历,删除和插入操作更加灵活。如果丢失了头结点的指针,仍可以通过尾节点找到链表的其他节点。但双向链表需要维护两个指针,增加了存储空间的消耗和代码的复杂性。

结语

链表和双向链表作为基础的数据结构,在处理动态数据和顺序查找中具有显著优势。通过对Go语言中链表的实现,读者可以更深入理解如何在实际开发中使用这些数据结构来提高程序的性能和可维护性。

相关文章:

Go语言中的链表与双向链表实现

链表基础 链表是一种由有限元素组成的数据结构&#xff0c;其中每个元素至少使用两个内存空间&#xff1a;一个存储实际数据&#xff0c;另一个存储指向下一个元素的指针&#xff0c;从而形成一个元素序列构成链表。链表的第一个元素称为头结点&#xff0c;而最后一个元素通常…...

开始一个WPF项目时的记忆重载入

目前在工业软件的UI开发方案选择中&#xff0c;WPF仍然是一个重要的选项。 但是其固有的复杂性&#xff0c;对于像我这样&#xff0c;并不是一直在从事界面开发的人来说&#xff0c;每次重启&#xff0c;都需要一两天的适应的时间。所以这里稍微写一个笔记。 还是老办法&…...

用go语言实现树和哈希表算法

算法复杂度 判断一个算法的效率通常基于其计算复杂度&#xff0c;这主要与算法访问输入数据的次数有关。计算机科学中常用大O表示法来描述算法的复杂度。例如&#xff0c;O(n)的算法只需访问一次输入数据&#xff0c;因此优于O(n)的算法&#xff0c;后者则优于O(n)的算法&…...

基于SpringBoot+Vue+MySQL的校园健康驿站管理系统

系统展示 用户前台界面 管理员后台界面 系统背景 本文设计并实现了一个基于SpringBoot后端、Vue前端与MySQL数据库的校园健康驿站管理系统。该系统旨在通过数字化手段&#xff0c;全面管理学生的健康信息&#xff0c;包括体温监测、疫苗接种记录、健康状况申报等&#xff0c;为…...

深入理解MATLAB中的事件处理机制

在MATLAB中&#xff0c;事件处理机制是一种强大的工具&#xff0c;它允许对象之间的交互和通信。这种机制基于观察者设计模式&#xff0c;其中一个对象&#xff08;观察者&#xff09;监听另一个对象&#xff08;发布者&#xff09;的状态变化。当发布者的状态发生变化时&#…...

线程--线程同步

这里写目录标题 同步概念线程同步概念数据混乱原因 互斥量原理锁的注意事项1、cpu时间轮片2、建议锁总结 使用锁来管理线程同步问题产生主要函数init、destorylock、unlock代码注意事项&#xff08;锁的粒度&#xff09; try锁死锁出现原因图解 读写锁特性图解函数总览init、de…...

【QT】Qt窗口

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;折纸花满衣 &#x1f3e0;个人专栏&#xff1a;QT 目录 &#x1f449;&#x1f3fb;菜单栏设置&#x1f449;&#x1f3fb;QToolBar练习 &#x1f449;&#x1f3fb;QStausBar&#x1f449;&#x1f3fb;Q…...

场外个股期权怎么给股票加杠杆?

今天期权懂带你了解场外个股期权怎么给股票加杠杆&#xff1f;场外期权交易通过向证券公司支付一定额度的股票期权费&#xff0c;然后买入大额的股票持仓&#xff0c;从而实现的杠杆交易。 买入看涨期权 操作&#xff1a;支付权利金购买看涨期权。 杠杆作用&#xff1a; 期…...

【Docker部署ELK】(7.15)

1、拉取镜像 docker pull docker.elastic.co/elasticsearch/elasticsearch:7.15.0 docker pull docker.elastic.co/kibana/kibana:7.15.0 docker pull docker.elastic.co/logstash/logstash:7.15.02、配置文件&#xff08;解压资源到D盘DOCKER目录下&#xff09; 2.1 配置文件…...

UE4_后期处理_后期处理材质及后期处理体积一

后期处理效果 在渲染之前应用于整个渲染场景的效果。 后期处理效果&#xff08;Post-processing effect&#xff09;使美术师和设计师能够对影响颜色、色调映射、光照的属性和功能进行组合选择&#xff0c;从而定义场景的整体外观。要访问这些功能&#xff0c;可以将一种称为…...

【PyQt6 应用程序】基于QtDesigner做一个用户登录页面

在当今的软件开发领域,用户界面(UI)设计和后端编程是创建现代、互动应用程序的两大重要组成部分。尤其是在开发具有用户登录功能的应用程序时,不仅要注重外观和用户体验的设计,还要确保后端逻辑的安全性和可靠性。 本文将介绍如何使用PyQt6框架结合UI设计,实现一个简单而…...

Ollama—87.4k star 的开源大模型服务框架!!

这一年来&#xff0c;AI 发展的越来越快&#xff0c;大模型使用的门槛也越来越低&#xff0c;每个人都可以在自己的本地运行大模型。今天再给大家介绍一个最厉害的开源大模型服务框架——ollama。 项目介绍 Ollama 是一个开源的大语言模型&#xff08;LLM&#xff09;服务工具…...

MySQL表的操作与数据类型

目录 前言 一、表的操作 1.创建一个表 2.查看表的结构 3.修改表 4.删除一个表 二、 MySQL的数据类型 0.数据类型一览&#xff1a; 1.整数类型 2.位类型 3.小数类型 4.字符类型 前言 在MySQL库的操作一文中介绍了有关MySQL库的操作&#xff0c;本节要讲解的是由库管理的结构——…...

mysql把某一个字段的值中的aa,替换成bb

UPDATE my_table SET my_column REPLACE(my_column, aa, bb); 例 假设my_table表在替换前的数据如下&#xff1a; idmy_column1hello aa2world aa aa3no aa here 执行上述UPDATE语句后&#xff0c;my_table表的数据将变为&#xff1a; idmy_column1hello bb2world bb b…...

【系统架构设计师】原型模式详解

原型模式详解 1. 什么是原型模式? 原型模式(Prototype Pattern)是一种创建型设计模式,它允许通过复制已有的对象来创建新的对象,而不是通过类实例化来创建新对象。通过这种方式,原型模式能够减少创建对象的开销,尤其是当对象的创建过程非常复杂或者耗费资源时。原型模…...

Spring @Async 深度解读:默认线程池执行器的配置与优化

在Spring中&#xff0c;Async注解用于异步执行方法。默认情况下&#xff0c;Async注解的任务是由一个线程池执行的。然而&#xff0c;这个默认的线程池是如何初始化的呢&#xff1f;本文将深入探讨这一过程&#xff0c;帮助你理解Spring异步任务背后的线程池执行器的初始化原理…...

手把手教你用护核纪元地心护核者用服务器开服联机

1、购买后登录服务器面板&#xff08;百度莱卡云面板&#xff09; 登录面板的信息在绿色的登陆面板按键下方&#xff0c;不是你的莱卡云账号 进入控制面板后会出现正在安装的界面&#xff0c;安装大约3分钟&#xff08;如长时间处于安装中请联系我们的客服人员&#xff09; 2、…...

Log4j 1.x如何升级到Log4j 2.x

Log4j 1.x升级到Log4j 2.x是一个涉及多个步骤的过程&#xff0c;主要包括删除旧版本、添加新版本依赖、配置新版本的配置文件等。以下是一个详细的升级步骤指南&#xff1a; 一、准备阶段 了解当前项目依赖&#xff1a; 检查项目中所有使用Log4j 1.x的地方&#xff0c;包括ja…...

CloudFlare问题与CDN问题

昨天将腾讯云的解析转移到Cloudflare中了&#xff0c;结果今天发现网站崩了&#xff0c;显示重定向次数过多&#xff0c;昨天估计是因为浏览器缓存&#xff0c;所以没有发现问题 问题一&#xff1a;强制HTTPS 当时看到CloudFlare的强制https时就想到了我的宝塔面板也开着强制h…...

[Linux]:文件(上)

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;Linux学习 贝蒂的主页&#xff1a;Betty’s blog 1. C语言文件操作 C语言文件操作接口如下&#xff0c;详情可参照——C语言文…...

Python爬虫实战:研究MechanicalSoup库相关技术

一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建&#xff08;全平台详解&#xff09; 在开始使用 React Native 开发移动应用之前&#xff0c;正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南&#xff0c;涵盖 macOS 和 Windows 平台的配置步骤&#xff0c;如何在 Android 和 iOS…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

Debian系统简介

目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版&#xff…...

【磁盘】每天掌握一个Linux命令 - iostat

目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat&#xff08;I/O Statistics&#xff09;是Linux系统下用于监视系统输入输出设备和CPU使…...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...