【数据结构与算法】链表的实现以及相关算法

目录

单选链表的基本实现

有序列表的合并(双指针法)

链表的反转 

链表实现两数之和 

判定链表是否有环


双链表的实现

public class DLinkedList<E> {private Node<E> first;private Node<E> last;int size;/*** 头插法* @param item*/public void addFirst(E item){Node<E> f =first;Node<E> newNode =new Node<E>(null,item,f);first =newNode;if (f==null){last =newNode;}else {f.prev=newNode;}size++;}/*** 尾插法* @param item*/public void addLast(E item){Node<E> l =last;Node<E> newNode =new Node<E>(l,item,null);last =newNode;if (l==null){first=newNode;}else {l.next=newNode;}size++;}/*** 删除头节点*/public void deleteFirst(){Node<E> f =first;Node<E> n =first.next;f.next =null;f.item=null;first=n;if (n==null){last=null;}else {n.prev=null;}size--;}/*** 删除尾节点*/public void deleteLast(){Node<E> l =last;Node<E> p =last.prev;l.item=null;l.prev=null;last=p;if (p==null){first=null;}else {p.next=null;}size--;}/*** 从头开始遍历* @return*/public String toStringForFirst() {StringJoiner sj =new StringJoiner("->");for (Node<E> n= first;n!=null;n =n.next){sj.add(n.item.toString());}return sj.toString();}/*** 从尾开始遍历* @return*/public String toStringForLast(){StringJoiner sj =new StringJoiner("<-");for (Node<E> n =last;n!=null;n=n.prev){sj.add(n.item.toString());}return sj.toString();}@Overridepublic String toString() {StringJoiner sj =new StringJoiner("<->");for (Node<E> n= first;n!=null;n =n.next){sj.add(n.item.toString());}return sj.toString();}/*** 节点内部类* @param <E>*/static class Node<E>{private E item;private Node<E> prev;private Node<E> next;Node(Node<E> prev,E item,Node<E> next){this.prev=prev;this.item=item;this.next=next;}}
}

单链表的实现

public class LinkedList1 {//头节点Node first;//尾节点Node last;//大小int size = 0;//头插法public void addFirst(int v) {Node newNode = new Node(v);Node f = first;first = newNode;if (f == null) {last = newNode;} else {newNode.next = f;}size++;}//尾插法public void addLast(int v) {Node newNode = new Node(v);Node l = last;last = newNode;if (l == null) {first = newNode;} else {l.next = newNode;}size++;}//使用节点尾插public void addNode(Node node){if (last ==null){last=node;first=node;}else {Node l =last;l.next=node;last=node;}}//链表的遍历@Overridepublic String toString() {StringJoiner sj = new StringJoiner("->");for (Node n = first; n != null; n = n.next) {sj.add(String.valueOf(n.val));}return sj.toString();}public static class Node {int val;Node next;Node(int val) {this.val = val;}}
}

有序列表的合并(双指针法)

//链表的有序合并排序public static LinkedList1 merge(LinkedList1 list1, LinkedList1 list2) {Node n1 = list1.first, n2 = list2.first;LinkedList1 result = new LinkedList1();while (n1 != null || n2 != null) {if (n1 == null) {result.addLast(n2.val);n2 = n2.next;continue;}if (n2 == null) {result.addLast(n1.val);n1 = n1.next;continue;}if (n1.val < n2.val) {result.addLast(n1.val);n1 = n1.next;} else {result.addLast(n2.val);n2 = n2.next;}}return result;}

 测试

LinkedList1 linkedList1 =new LinkedList1();linkedList1.addLast(1);linkedList1.addLast(4);linkedList1.addLast(6);LinkedList1 linkedList2 =new LinkedList1();linkedList2.addLast(2);linkedList2.addLast(3);linkedList2.addLast(5);linkedList2.addLast(9);System.out.println("链表1:"+linkedList1);System.out.println("链表2:"+linkedList2);//有序链表的合并排序System.out.println("链表1与链表2合并:"+LinkedList1.merge(linkedList1, linkedList2));

链表的反转 

//链表的反转public static LinkedList1 reverseLinked(LinkedList1 list1) {Stack<Node> stack = new Stack<>();for (Node n = list1.first; n != null; n = n.next) {stack.add(n);}LinkedList1 result = new LinkedList1();while (!stack.isEmpty()) {result.addLast(stack.pop().val);}return result;}

测试

        LinkedList1 linkedList1 =new LinkedList1();linkedList1.addLast(1);linkedList1.addLast(4);linkedList1.addLast(6);System.out.println("链表1:"+linkedList1);//链表的反转System.out.println("链表1反转后:"+LinkedList1.reverseLinked(linkedList1));

测试结果

链表实现两数之和 

    //两数之和public static LinkedList1 addNumber(LinkedList1 list1, LinkedList1 list2) {Node n1 = list1.first, n2 = list2.first;LinkedList1 result = new LinkedList1();int carry = 0;while (n1 != null || n2 != null) {int x = n1 != null ? n1.val : 0;int y = n2 != null ? n2.val : 0;int sum = x + y + carry;carry = sum / 10;result.addLast(sum % 10);if (n1 != null) {n1 = n1.next;}if (n2 != null) {n2 = n2.next;}}if (carry != 0) {result.addLast(carry);}return result;}

测试

        LinkedList1 linkedList1 =new LinkedList1();linkedList1.addLast(1);linkedList1.addLast(4);linkedList1.addLast(6);LinkedList1 linkedList2 =new LinkedList1();linkedList2.addLast(2);linkedList2.addLast(3);linkedList2.addLast(5);linkedList2.addLast(9);//两数之和System.out.println("链表1:"+linkedList1);System.out.println("链表2:"+linkedList2);System.out.println("链表1+链表2:"+LinkedList1.addNumber(linkedList1,linkedList2));

测试结果(注意从左到右依次是个十百位)

判定链表是否有环

方法一 通过set集合

    //set集合判断是否有环public static boolean hasCycle(Node node) {Set<Node> set = new HashSet<>();while (node != null) {if (set.contains(node)) {return true;}set.add(node);node = node.next;}return false;}

方法二 通过快慢指针

    //快慢指针判断是否有环public static boolean hasCycle2(Node node) {Node fast = node;//快指针Node slow = node;//慢指针//判断是不是空节点if (node == null) {return false;}while (fast != null && fast.next != null && slow != null) {fast = fast.next.next;slow = slow.next;if (fast == slow) {return true;}}return false;}

测试 无论方法一还是二 测试结果都是相同 一般使用方法二 效率更高 更节省资源

        LinkedList1.Node node1 =new LinkedList1.Node(1);LinkedList1.Node node2 =new LinkedList1.Node(2);LinkedList1.Node node3 =new LinkedList1.Node(3);LinkedList1.Node node4 =new LinkedList1.Node(4);LinkedList1.Node node5 =new LinkedList1.Node(5);node1.next=node2;node2.next=node3;node3.next=node4;node4.next=node5;node5.next=node3;//环 注意这是专门设置的环//set集合判断是否有环System.out.println("set集合判断是否有环:"+LinkedList1.hasCycle(node1));//快慢指针判断是否有环System.out.println("快慢指针判断是否有环:"+LinkedList1.hasCycle2(node1));

测试结果

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Prettier - Code formatter格式化规则文件

文章目录 前言安装使用 前言 先前公司在规范代码时,由于个人业务繁忙跟技术总监是后端出身用的IDEA不熟悉vsCode;以及大多数时都自己一个人负责一个项目,当时并不看重这些;最近在整理vue3tsvite的脚手架模板(平时工作用的react),开始整理格式化代码,方便之后 vue 和 react 中应…

Android Shape设置背景

设置背景时&#xff0c;经常这样 android:background“drawable/xxx” 。如果是纯色图片&#xff0c;可以考虑用 shape 替代。 shape 相比图片&#xff0c;减少资源占用&#xff0c;缩减APK体积。 开始使用。 <?xml version"1.0" encoding"utf-8"?…

高效查询大量快递信息,轻松掌握技巧

在如今快节奏的生活中&#xff0c;快递已经成为我们日常不可或缺的一部分。然而&#xff0c;对于一些忙碌的人来说&#xff0c;单个查询每一个快递单号可能会浪费太多时间。因此&#xff0c;我们需要一款可以帮助我们批量查询快递的软件。 在市场上&#xff0c;有很多款专门用于…

【2023年11月第四版教材】第15章《风险管理》(第四部分)

第15章《风险管理》&#xff08;第四部分&#xff09; 8 过程4-实施定量风险分析8.1 实施定量风险分析★★★8.2 数据分析★★★8.3 定量成本风险分析S曲线示例8.4 决策树示例8.5 龙卷风图示例8.6 项目文件&#xff08;更新&#xff09;★★★ 9 过程5-规划风险应对9.1 规划风险…

【2023款奔驰改款E260 L运动型:豪华与性能的完美结合】

在汽车市场中&#xff0c;奔驰一直以其卓越的品质和卓越的性能赢得了消费者的喜爱。而2023款奔驰改款E260 L运动型&#xff0c;更是将豪华与性能完美结合&#xff0c;让人无法抗拒。首先&#xff0c;让我们来看一下这款车的外观设计。新款E260 L运动型的前脸设计更加犀利&#…

【Linux】——基操指令(一)

个人主页 代码仓库 C语言专栏 初阶数据结构专栏 Linux专栏 LeetCode刷题 算法专栏 目录 前言 基操前的碎碎念 计算机的层状结构 基础指令 查看登录用户指令 查看用户指令 查看当前所处工作目录 清屏指令 基操指令 ls命令 cd命令 makdir指令 rmdir指令 &…

十二、MySql的事务(下)

文章目录 一、事务隔离级别二、如何理解隔离性三、隔离级别&#xff08;一&#xff09;读未提交【Read Uncommitted】&#xff1a;&#xff08;二&#xff09;读提交【Read Committed】 &#xff1a;&#xff08;三&#xff09;可重复读【Repeatable Read】&#xff1a;&#x…

【计算机网络笔记六】应用层(三)HTTP 的 Cookie、缓存控制、代理服务、短连接和长连接

HTTP 的 Cookie HTTP 的 Cookie 机制要用到两个字段&#xff1a;响应头字段 Set-Cookie 和请求头字段 Cookie。 Cookie 可以设置多个 key-value 对&#xff0c; 响应头中可以设置多个 Set-Cookie 字段&#xff0c;请求头Cookie后面可以设置多个键值对&#xff0c;用分号隔开&a…

西门子KTP触摸屏做画面时如何把设备图片或Logo做到画面上?

西门子KTP触摸屏做画面时如何把设备图片或Logo做到画面上&#xff1f; 如下图所示&#xff0c;新建一个项目&#xff0c;添加一个触摸屏设备&#xff0c;这里以TP1200 Comfort触摸屏为例进行说明&#xff0c;双击进入根画面&#xff0c; 如下图所示&#xff0c;在右侧的工具箱中…

学习路之工具--SecureCRT的下载、安装

百度盘&#xff1a; 链接: https://pan.baidu.com/s/1r3HjEj053cKys54DTqLM4A?pwdgcac 提取码: gcac 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 感谢大佬 简单介绍下SecureCRT SecureCRT是一款支持SSH&#xff08;SSH1和SSH2&#xff09;的终端仿真程序&a…

[C++ 网络协议] 多线程服务器端

具有代表性的并发服务器端实现模型和方法&#xff1a; 多进程服务器&#xff1a;通过创建多个进程提供服务。 多路复用服务器&#xff1a;通过捆绑并统一管理I/O对象提供服务。 多线程服务器&#xff1a;通过生成与客户端等量的线程提供服务。✔ 目录 1. 线程的概念 1.1 为什…

静态链接与动态链接

目录 静态链接 地址空间分配 静态链接的详细过程 静态链接库 动态链接 位置无关代码 延迟绑定机制 本篇会重点介绍静态链接&#xff0c;动态链接&#xff0c;延迟绑定机制 问&#xff1a;两个或者多个不同的目标文件是如何组成一个可执行文件的呢? 答&#xff1a;这就…

数据结构 - 线段树的运用

数据结构 - 线段树的运用 前言一. 线段树的运用1.1 区间和 - 线段树节点的成员变量1.2 线段树的构建1.3 线段树的区间和查询1.4 线段树的区间和更新1.5 完整代码 二. 线段树的动态扩建2.1 向下递推2.2 向上递推2.3 更新操作2.4 查询操作2.5 完整代码 三. 线段树的使用案例3.1 定…

Unity之NetCode多人网络游戏联机对战教程(3)--NetworkObject组件讲解

文章目录 NetworkObjectAlways Replicate As RootSynchronization TransformActive Scene SynchronizationScene Migration SynchronizationSpawn With ObserversDont Destroy With OwnerAuto Object Parent Sync 后话 NetworkObject 为了复制任何Netcode感知属性或发送/接收R…

Python大数据之pandas快速入门(一)

文章目录 pandas快速入门学习目标1. DataFrame 和 Series 简介2. 加载数据集(csv和tsv)2.1 csv和tsv文件格式简介2.2 加载数据集(tsv和csv) pandas快速入门 学习目标 能够知道 DataFrame 和 Series 数据结构能够加载 csv 和 tsv 数据集能够区分 DataFrame 的行列标签和行列位…

FPGA project : uart232_ram_vga

重点学习&#xff1a; 本实验重点学习了双口ram解决多bit跨时钟域同步处理的问题。 其实signal port ram&#xff0c;它的输入口和输出口分别用不同的时钟&#xff0c;也可以解决这个问题。 让我意识到的比较重要的事情&#xff1a; 1&#xff0c;代码设计中&#xff0c;一…

经典题记录 字符串相加/相乘

1. LeetCode 415 字符串相加 代码一&#xff1a;代码简短&#xff0c;但需要借助额外的一个string来保存结果&#xff0c;更占用内存。 class Solution { public:string addStrings(string num1, string num2) {string ans"";int size1num1.size();int size2num2.si…

Qt_C++读写NFC标签Ntag支持windows国产linux操作系统

本示例使用的发卡器&#xff1a;Android Linux RFID读写器NFC发卡器WEB可编程NDEF文本/智能海报/-淘宝网 (taobao.com) ntag2标签存储结构说明 #include "mainwindow.h" #include "./ui_mainwindow.h" #include <QDebug> #include "QLibrary&…

Django REST Farmowork初探

1.简介 Django REST framework &#xff08;简称&#xff1a;DRF&#xff09;是一个强大而灵活的 Web API 工具。 遵循RESTFullAPI风格&#xff0c;功能完善&#xff0c;可快速开发API平台。 官网文档&#xff1a;https://www.django-rest-framework.org 2. framwork的安装 …

界面组件DevExpress WPF v23.2新功能预览 - 更轻量级的主题

本文主要描述了DevExpress WPF即将在几个月之后发布的v23.2中包含的新功能&#xff0c;持续关注我们获取更多最新资讯哦~ P.S&#xff1a;DevExpress WPF拥有120个控件和库&#xff0c;将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress WPF能创建有着强…