双向链表也叫双链表

双向链表也叫双链表

双向链表也叫双链表
每个节点都有两个指针,分别指向 直接前驱节点、直接后继节点

双向链表中任意一个节点,都可以通过通过它的前驱节点和后继节点,访问其他节点

节点如下
在这里插入图片描述
节点定义
ListNode
// 节点的值
T element;
// 前置节点
ListNode preNode;
// 后置节点
ListNode nextNode;

链表提供以下方法

项目Value
PushFront(T t)将元素插入到链表第一个位置
PushBack(T t)将元素插入到链表最后一个位置
Front()第一个节点
Back()最后一个节点
MakeEmpty()清空链表
IsEmpty()判断链表是否为空
Size()获取链表中数据个数
Find(T t)查找节点
Delete(T t)删除节点
Delete(ListNode node)删除节点
InsertAsNext(ListNode node, ListNode next)将 next 插入到 node 后
Begin()迭代器开始
End()迭代器结束
Deduplicate()无序链表删除重复元素
Uniquify()有序链表删除重复元素
List Traverse()迭代遍历获取所有元素
Swap(ListNode node1, ListNode node2)交换两个节点的值
Sort(Comparison comparison)排序,comparison 是比较函数

C# 代码实现如下

    /// <summary>/// 链表节点/// </summary>/// <typeparam name="T"></typeparam>public class ListNode<T> where T : IComparable<T>{// 节点的值private T element;// 前置节点private ListNode<T> preNode;// 后置节点private ListNode<T> nextNode;public ListNode(){}public ListNode(T v){element = v;}public ListNode(T v, ListNode<T> pre, ListNode<T> next){element = v;preNode = pre;nextNode = next;}public T Element{get { return element; }set { element = value; }}public ListNode<T> PreNode{get { return preNode; }set { preNode = value; }}public ListNode<T> NextNode{get { return nextNode; }set { nextNode = value; }}}/// <summary>/// 链表迭代器/// </summary>/// <typeparam name="T"></typeparam>public class LinkListIterator<T> where T : IComparable<T>{private ListNode<T> node;public LinkListIterator(ListNode<T> node){this.node = node;}public ListNode<T> Node{get { return node; }}public T Element{get{return node.Element;}}/// <summary>/// 重写 == 方法/// </summary>/// <param name="iteratorL"></param>/// <param name="iteratorR"></param>/// <returns></returns>public static bool operator ==(LinkListIterator<T> iteratorL, LinkListIterator<T> iteratorR){return null != iteratorL.node && null != iteratorR.node && iteratorL.node == iteratorR.node;}/// <summary>/// 重写 != 方法/// </summary>/// <param name="iteratorL"></param>/// <param name="iteratorR"></param>/// <returns></returns>public static bool operator !=(LinkListIterator<T> iteratorL, LinkListIterator<T> iteratorR){return null == iteratorL.node || null == iteratorR.node || iteratorL.node != iteratorR.node;}/// <summary>/// 重写 ++ 方法/// </summary>/// <param name="iterator"></param>/// <returns></returns>public static LinkListIterator<T> operator ++(LinkListIterator<T> iterator){iterator.node = iterator.node.NextNode;return iterator;}/// <summary>/// 重写 -- 方法/// </summary>/// <param name="iterator"></param>/// <returns></returns>public static LinkListIterator<T> operator --(LinkListIterator<T> iterator){iterator.node = iterator.node.PreNode;return iterator;}public override bool Equals(object obj){return base.Equals(obj);}public override int GetHashCode(){return base.GetHashCode();}}/// <summary>/// 链表/// </summary>/// <typeparam name="T"></typeparam>public class LinkList<T> where T : IComparable<T>{/// <summary>/// 头节点/// </summary>private ListNode<T> _header;/// <summary>/// 尾节点/// </summary>private ListNode<T> _trailer;  // 除去 头、尾,节点的个数private int _size;public LinkList(){// 为了减少操作上的复杂度// 头节点和尾节点一直存在,添加、删除都是在 头节点、尾节点 中间操作_header = new ListNode<T>();_trailer = new ListNode<T>();_header.PreNode = null;_header.NextNode = _trailer;_trailer.PreNode = _header;_trailer.NextNode = null;}/// <summary>/// 迭代器开始/// </summary>/// <returns></returns>public LinkListIterator<T> Begin(){return new LinkListIterator<T>(_header.NextNode);}/// <summary>/// 迭代器结束/// </summary>/// <returns></returns>public LinkListIterator<T> End(){return new LinkListIterator<T>(_trailer);}/// <summary>/// 第一个元素/// </summary>public ListNode<T> Front(){return Size() > 0 ? _header.NextNode : null;}/// <summary>/// 最后一个元素/// </summary>public ListNode<T> Back(){return Size() > 0 ? _trailer.PreNode : null;}/// <summary>/// 清空链表/// </summary>public void MakeEmpty(){_header.NextNode = _trailer;_trailer.PreNode = _header;_size = 0;}/// <summary>/// 链表为空/// </summary>public bool IsEmpty(){return _header.NextNode == _trailer;}/// <summary>/// 链表元素个数/// </summary>public int Size(){return _size;}/// <summary>/// 查找元素指针位置/// </summary>public ListNode<T> Find(T t){ListNode<T> temp = _header.NextNode;while (temp != _trailer){if (temp.Element.CompareTo(t) == 0){return temp;}temp = temp.NextNode;}return null;}/// <summary>/// 删除元素/// </summary>public void Delete(T t){ListNode<T> node = Find(t);Delete(node);}public void Delete(ListNode<T> node){if (null != node){node.PreNode.NextNode = node.NextNode;node.NextNode.PreNode = node.PreNode;--_size;}}/// <summary>/// 将元素插入到链表第一个位置/// </summary>/// <param name="t"></param>public void PushFront(T t){ListNode<T> newNode = new ListNode<T>(t);InsertAsPre(_header.NextNode, newNode);}/// <summary>/// 将元素插入到链表最后一个位置/// </summary>/// <param name="t"></param>public void PushBack(T t){ListNode<T> newNode = new ListNode<T>(t);InsertAsPre(_trailer, newNode);}private void InsertAsPre(ListNode<T> node, ListNode<T> next){InsertAsNext(node.PreNode, next);}/// <summary>/// 将 next 插入到 node 后/// </summary>/// <param name="node"></param>/// <param name="next"></param>public void InsertAsNext(ListNode<T> node, ListNode<T> next){if (node == _trailer){return;}next.PreNode = node;next.NextNode = node.NextNode;node.NextNode.PreNode = next;node.NextNode = next;++_size;}/// <summary>/// 无序链表删除重复元素/// </summary>public void Deduplicate(){for (ListNode<T> node = _header.NextNode; node != _trailer; node = node.NextNode){for (ListNode<T> temp = node.NextNode; temp != _trailer; temp = temp.NextNode){if (node.Element.CompareTo(temp.Element) == 0){Delete(temp);}}}}/// <summary>/// 有序链表删除重复元素/// </summary>public void Uniquify(){ListNode<T> node = _header.NextNode;while ( node != _trailer){ListNode<T> next = node.NextNode;if (next != _trailer && next.Element.CompareTo(node.Element) == 0){Delete(next);continue;}node = node.NextNode;}}/// <summary>/// 遍历/// </summary>public List<T> Traverse(){List<T> list = new List<T>();for (LinkListIterator<T> iterator = Begin(); iterator != End(); ++iterator){list.Add(iterator.Element);}return list;}/// <summary>/// 交换两个节点位置/// </summary>public void Swap(ListNode<T> node1, ListNode<T> node2){if (node1.NextNode == node2){Swap(node1.PreNode, node2.NextNode, node1, node2);}else if (node2.NextNode == node1){Swap(node2.PreNode, node1.NextNode, node2, node1);}else{Swap(node1.PreNode, node2.NextNode, node1, node2);}}/// <summary>/// 交换两个节点位置/// </summary>/// <param name="pre"></param>/// <param name="next"></param>/// <param name="node1"></param>/// <param name="node2"></param>private void Swap(ListNode<T> pre, ListNode<T> next, ListNode<T> node1, ListNode<T> node2){Delete(node1);Delete(node2);InsertAsNext(pre, node2);InsertAsPre(next, node1);}/// <summary>/// 排序/// </summary>public void Sort(Comparison<T> comparison){ListNode<T> begin = _header.NextNode;if (null == begin || begin.NextNode == _trailer){return;}for (ListNode<T> temp = begin.NextNode; temp != _trailer; temp = temp.NextNode){T element = temp.Element;ListNode<T> preNode = temp.PreNode;while (preNode != _header.NextNode.PreNode && comparison(preNode.Element, element) > 0){preNode.NextNode.Element = preNode.Element;preNode = preNode.PreNode;}preNode.NextNode.Element = element;}}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/313079.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

康谋技术 | 深入探讨:自动驾驶中的相机标定技术

随着自动驾驶技术的快速发展&#xff0c;多传感器的数据采集和融合可以显著提高系统的冗余度和容错性&#xff0c;进而保证决策的快速性和正确性。在项目开发迭代过程中&#xff0c;传感器标定扮演着至关重要的角色&#xff0c;它位于数据采集平台与感知融合算法之间&#xff0…

【R语言】混合图:小提琴图+箱线图

{ggstatsplot} 是 {ggplot2} 包的扩展&#xff0c;用于创建图形&#xff0c;其中包含信息丰富的绘图本身中包含的统计测试的详细信息。在典型的探索性数据分析工作流程中&#xff0c;数据可视化和统计建模是两个不同的阶段&#xff1a;可视化通知建模&#xff0c;而建模又可以建…

【FreeRTOS】使用CubeMX快速移植FreeRTOS工程到蓝桥杯开发板(STM32G431RBT6)

使用CubeMX快速创建FreeRTOS工程到蓝桥杯开发板&#xff08;STM32G431RBT6&#xff09; CubeMX配置CubeMX基础工程的配置☆FreeRTOS相关配置FreeRTOS配置选项卡的解释 软件工程架构与程序设计小综合&#xff1a;任务的创建删除、挂起与恢复设计cubexMX配置创建任务软件程序设计…

工业自动化,3D视觉技术3C薄片自动化上料

随着制造业的快速发展&#xff0c;3C行业对薄片类零件的上料需求日益增长。传统的上料方式往往依赖于人工操作&#xff0c;效率低下且存在误差。为了解决这一问题&#xff0c;3D视觉技术应运而生&#xff0c;为3C薄片自动化上料提供了强大的技术支持。本文将探讨3D视觉技术如何…

HarmonyOS开发实例:【分布式手写板】

介绍 本篇Codelab使用设备管理及分布式键值数据库能力&#xff0c;实现多设备之间手写板应用拉起及同步书写内容的功能。操作流程&#xff1a; 设备连接同一无线网络&#xff0c;安装分布式手写板应用。进入应用&#xff0c;点击允许使用多设备协同&#xff0c;点击主页上查询…

stm32f103c8t6学习笔记(学习B站up江科大自化协)-SPI

SPI通信 SPI&#xff0c;&#xff08;serial peripheral interface&#xff09;&#xff0c;字面翻译是串行外设接口&#xff0c;是一种通用的数据总线&#xff0c;适用于主控和外挂芯片之间的通信&#xff0c;与IIC应用领域非常相似。 IIC无论是在硬件电路还是在软件时序设计…

Covalent Network(CQT)宣布推出面向 Cronos 生态的捐赠计划与 API 积分,为 Web3 创新赋能

为了促进 Web3 领域的创新&#xff0c;Covalent Network&#xff08;CQT&#xff09;宣布将其捐赠计划向 Cronos 生态系统中的开发者拓展。这一战略性举措&#xff0c;旨在通过向 Cronos 网络中基于 Covalent Network&#xff08;CQT&#xff09;API 构建的项目提供支持和资源&…

多模态大语言模型综述

节前&#xff0c;我们星球组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、参加社招和校招面试的同学&#xff0c;针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。 汇总…

【网络安全 | 密码学】JWT基础知识及攻击方式详析

前言 JWT&#xff08;Json Web Token&#xff09;是一种用于在网络应用之间安全地传输信息的开放标准。它通过将用户信息以JSON格式加密并封装在一个token中&#xff0c;然后将该token发送给服务端进行验证&#xff0c;从而实现身份验证和授权。 流程 JWT的加密和解密过程如…

HTML5漫画风格个人介绍源码

源码介绍 HTML5漫画风格个人介绍源码&#xff0c;源码由HTMLCSSJS组成&#xff0c;记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果&#xff0c;也可以上传到服务器里面&#xff0c;重定向这个界面 效果截图 源码下载 HTML5漫画风格…

【honggfuzz学习笔记】honggfuzz的基本特性

本文架构 1.动机2.honggfuzz的基本概念官网描述解读 3. honggfuzz的反馈驱动(Feedback-Driven)软件驱动反馈&#xff08;software-based coverage-guided fuzzing&#xff09;代码覆盖率代码覆盖率的计量单位 代码覆盖率的统计方式 硬件驱动反馈&#xff08; hardware-based co…

MCU最小系统晶振模块设计

单片机的心脏&#xff1a;晶振 晶振模块 单片机有两个心脏&#xff0c;一个是8M的心脏&#xff0c;一个是32.768的心脏 8M的精度较低&#xff0c;所以需要外接一个32.768khz 为什么是8MHZ呢&#xff0c;因为内部自带的 频率越高&#xff0c;精度越高&#xff0c;功耗越大&am…

2024Guitar Pro 8.1 Mac 最新下载、安装、激活、换机图文教程

吉他爱好者必备神器&#xff1a;Guitar Pro v8.1.1 Build 17深度解析 随着数字音乐制作和学习的日益普及&#xff0c;越来越多的吉他爱好者开始寻找能够帮助他们提升技能、创作音乐的专业工具。在众多吉他制作软件中&#xff0c;Guitar Pro因其强大的功能和易用的界面备受推崇…

超平实版Pytorch CNN Conv2d

torch.nn.Conv2d 基本参数 in_channels (int) 输入的通道数量。比如一个2D的图片&#xff0c;由R、G、B三个通道的2D数据叠加。 out_channels (int) 输出的通道数量。 kernel_size (int or tuple) kernel&#xff08;也就是卷积核&#xff0c;也可…

2024第十五届蓝桥杯JavaB组省赛部分题目

目录 第三题 第四题 第五题 第六题 第七题 第八题 转载请声明出处&#xff0c;谢谢&#xff01; 填空题暂时可以移步另一篇文章&#xff1a;2024第十五届蓝桥杯 Java B组 填空题-CSDN博客 第三题 第四题 第五题 第六题 第七题 第八题 制作不易&#xff0c;还请点个赞支持…

go语言context

context在服务端编程基本都贯穿所有&#xff0c; Context 是请求的上下文信息。对于RPC Server来说&#xff0c;一般每接收一个新的请求&#xff0c;会产生一个新的Context&#xff0c;在进行内部的函数调用的时候&#xff0c;通过传递Context&#xff0c;可以让不同的函数、协…

pytest学习-pytorch单元测试

pytorch单元测试 一.公共模块[common.py]二.普通算子测试[test_clone.py]三.集合通信测试[test_ccl.py]四.测试命令五.测试报告 希望测试pytorch各种算子、block、网络等在不同硬件平台,不同软件版本下的计算误差、耗时、内存占用等指标. 本文基于torch.testing._internal 一…

春藤实业启动SAP S/4HANA Cloud Public Edition项目,与工博科技携手数字化转型之路

3月11日&#xff0c;广东省春藤实业有限公司&#xff08;以下简称“春藤实业”&#xff09;SAP S/4HANA Cloud Public Edition&#xff08;以下简称“SAP ERP公有云”&#xff09;项目正式启动。春藤实业董事长陈董、联络协调项目经理慕总、内部推行项目经理陈总以及工博董事长…

【函数式接口使用✈️✈️】通过具体的例子实现函数结合策略模式的使用

目录 前言 一、核心函数式接口 1. Consumer 2. Supplier 3. Function,> 二、场景模拟 1.面向对象设计 2. 策略接口实现&#xff08;以 Function 接口作为策略&#xff09; 三、对比 前言 在 Java 8 中引入了Stream API 新特性&#xff0c;这使得函数式编程风格进…

Chatgpt掘金之旅—有爱AI商业实战篇|品牌故事业务|(十六)

演示站点&#xff1a; https://ai.uaai.cn 对话模块 官方论坛&#xff1a; www.jingyuai.com 京娱AI 一、AI技术创业在品牌故事业务有哪些机会&#xff1f; 人工智能&#xff08;AI&#xff09;技术作为当今科技创新的前沿领域&#xff0c;为创业者提供了广阔的机会和挑战。随…