链表原理与实现:从单链表到LinkedList

1.链表的概念及结构

链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的 。 可以形象的理解,在逻辑上来看,链表就像是一节节火车车厢。

链表的分类:链表的结构有很多种,单向或双向、带头或不带头、循环或不循环。这篇文章就从最简单的链表结构讲起———不带头单向非循环链表(单链表)。

2.单链表模拟实现

为了更好的学习对于单链表的操作。我们自己模拟实现一些基本的功能。

1.准备工作

接口

package List;public interface IList {//头插法void addFirst(int data);//尾插法public void addLast(int data);//任意位置插入,第一个数据节点为0号下标public void addIndex(int index,int data);//查找是否包含关键字key是否在单链表当中public boolean contains(int key);//删除第一次出现关键字为key的节点public void remove(int key);//删除所有值为key的节点public void removeAllKey(int key);//得到单链表的长度public int size();//清空public void clear() ;//打印public void display() ;
}

通过实现接口中的抽象方法实现单链表增删查改的实现。

单链表的定义

单链表(SinglyLinkedList)的定义需要定义单个节点ListNode。单个节点有data存储数据,next存储下一个节点的引用。同时单链表还需要一个成员变量head存储单链表的头位置。基于以上的需要可以把ListNode定义为单链表的内部类。

public class SinglyLinkedList {public class ListNode{public int data;public ListNode next;public ListNode(int data) {this.data = data;}}public ListNode head;
}

2.具体接口实现

添加

头插
@Overridepublic void addFirst(int data) {ListNode newnode = new ListNode(data);newnode.next = head;head = newnode;}
尾插
@Overridepublic void addLast(int data) {ListNode newnode = new ListNode(data);//链表为空if(head == null){head = newnode;return;}//链表不为空,找尾尾插ListNode cur = head;while (cur.next != null){cur = cur.next;}cur.next = newnode;}
在index位置插入
private void CheckIndex(int index){int len = this.size();if(index < 0 || index > len){throw new IllegalIndexException("index不合法");}}@Overridepublic void addIndex(int index, int data) {try {CheckIndex(index);ListNode newnode = new ListNode(data);if(index == 0){addFirst(data);}if(index == size()){addLast(data);}ListNode cur = head;while(index - 1 != 0){cur = cur.next;index--;}newnode.next = cur.next;cur.next = newnode;}catch (IllegalIndexException e){e.printStackTrace();}}

 删除

删除找到第一个key值
@Overridepublic void remove(int key) {if(head == null){return;}//解决头节点问题if(head.data == key){head = head.next;return;}ListNode cur = head;while(cur.next.data != key){cur = cur.next;}ListNode del = cur.next;cur.next = del.next;}
删除所有等于key的值
@Overridepublic void removeAllKey(int key) {if(head == null){return;}ListNode prev = head;ListNode cur = head.next;while (cur != null){if(cur.data == key){prev.next = cur.next;}else {prev = cur;}cur = cur.next;}//解决头节点data等于key的情况if(head.data == key){head = head.next;}}

查找

@Overridepublic boolean contains(int key) {ListNode cur = head;while (cur != null){if(cur.data == key){return true;}cur = cur.next;}return false;}

得到size

@Overridepublic int size() {int count = 0;ListNode cur = head;while(cur != null){count++;cur = cur.next;}return count ;}

清空

@Overridepublic void clear() {ListNode cur = head;while(cur != null){ListNode ret = cur;cur.next = null;cur = ret.next;}head = null;}

打印

@Overridepublic void display() {ListNode cur = this.head;while(cur != null){System.out.print(cur.data + " ");cur = cur.next;}System.out.println();}

2.链表oj

看这篇文章:单链表oj练习(C语言版)

虽然是C语言完成的,但是做题的思想是一样的。

3.LinkedList的模拟实现

LinkedList是java标准库提供的双向链表的实现。还是一样为了更好的理解并运用,先自己模拟实现一个。

1.准备工作

接口

接口和上面的单链表接口一样。

MyLinkedList的定义

和上面的单链表不同的是ListNode里多一个prev用于存储上一个节点的引用MyLinkedList多一个成员last存储双向链表的尾

2.具体接口实现

添加

@Overridepublic void addFirst(int data) {ListNode newnode = new ListNode(data);if(head == null){head = last = newnode;}else {newnode.next = head;head.prev = newnode;head = newnode;}}@Overridepublic void addLast(int data) {ListNode newnode = new ListNode(data);if(head == null){head = last = newnode;}else {last.next = newnode;newnode.prev = last;last = newnode;}}private void CheckIndex(int index){if(index < 0 || index > size()){throw new IllegalIndexException("index位置不合法");}}private ListNode FindIndexnode(int index){ListNode cur = head;while(index-1 > 0){cur = cur.next;index--;}return cur;}@Overridepublic void addIndex(int index, int data) {try {CheckIndex(index);if(index == 0){addFirst(data);}if(index == size()){addLast(data);}ListNode newnode = new ListNode(data);ListNode cur = FindIndexnode(index);newnode.next = cur;cur.prev.next = newnode;newnode.prev = cur.prev;newnode.next = cur;}catch(IllegalIndexException e){e.printStackTrace();}}

删除

@Overridepublic void remove(int key) {ListNode cur = head;while(cur != null){if(cur.data == key){if(cur == head){head = head.next;if(head != null){head.prev = null;}}else {cur.prev.next = cur.next;if (cur.next == null) {last = last.prev;} else {cur.next.prev = cur.prev;}}return;}cur = cur.next;}}@Overridepublic void removeAllKey(int key) {ListNode cur = head;while(cur != null){if(cur.data == key){if(cur == head){head = head.next;if(head != null){head.prev = null;}}else {cur.prev.next = cur.next;if (cur.next == null) {last = last.prev;} else {cur.next.prev = cur.prev;}}}cur = cur.next;}}

查找 打印 得到size

和单链表一样,本质都是遍历链表

清空

@Overridepublic void clear() {ListNode cur = head;while(cur != null){ListNode Curn = cur.next;cur.prev = null;cur.next = null;cur = Curn;}head = last = head;}

4.LinkedList的使用 

1.构造

public static void main(String[] args) {// 构造一个空的LinkedListList<Integer> list1 = new LinkedList<>();List<String> list2 = new java.util.ArrayList<>();list2.add("JavaSE");list2.add("JavaWeb");list2.add("JavaEE");// 使用ArrayList构造LinkedListList<String> list3 = new LinkedList<>(list2);
}

2.其他方法 

 

 

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

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

相关文章

替换word中的excel

PostMapping("/make/report/target/performance/first") public AjaxResult makeTargetReportFirst(RequestBody MakeReportDTO makeReportDTO) {Map<String, String> textReplaceMap new HashMap<>();// 替换日期LocalDateTime nowData LocalDateTime…

深入探索百度智能云千帆AppBuilder:从零开始构建AI应用

在数字化转型的浪潮中&#xff0c;企业对高效、智能的应用开发平台的需求日益增长。百度智能云千帆AppBuilder&#xff08;以下简称AppBuilder&#xff09;凭借其强大的功能和灵活的开发方式&#xff0c;成为企业级大模型应用开发的理想选择。本文将详细介绍如何使用AppBuilder…

测试工程师要如何开展单元测试

单元测试是软件开发过程中至关重要的环节&#xff0c;它通过验证代码的最小可测试单元(如函数、方法或类)是否按预期工作&#xff0c;帮助开发团队在早期发现和修复缺陷&#xff0c;提升代码质量和可维护性。以下是测试工程师开展单元测试的详细步骤和方法&#xff1a; 一、理…

NODE-I916 I721模块化电脑发布,AI算力与超低功耗的完美平衡

在智能工业与边缘计算蓬勃发展的今天&#xff0c;企业对计算设备的性能与能效需求日益严苛。全新推出NODE-I916与NODE-I721模块化电脑&#xff0c;分别搭载英特尔 酷睿™ Ultra 平台与Alder Lake-N平台&#xff0c;以差异化CPU配置为核心&#xff0c;为AI推理、工业自动化及嵌入…

采集需要登录网站的教程

有些网站需要用户登录才能显示相关信息&#xff0c;如果要采集这类网站&#xff0c;有以下几个方法&#xff1a; 1. 写发布模块来抓包获取post的数据&#xff1b; 2. 有些采集器内置浏览器获取这些信息&#xff0c;但是经常获取的不准确&#xff0c;可靠性太低&#xff1b; 3. …

六足连杆爬行机器人的simulink建模与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序 4.系统原理简介 5.完整工程文件 1.课题概述 六足连杆爬行机器人的simulink建模与仿真。通过simulink&#xff0c;对六足机器人的六足以及机身进行simulink建模&#xff0c;模拟其行走&#xff0c;仿真输出机器人行走时六足的坐…

什么是物联网 (IoT):2024 年物联网概述

物联网&#xff08;IoT&#xff09;是一个有望彻底改变我们生活、工作以及与环境互动方式的概念。如今&#xff0c;越来越多的新兴企业和老牌企业都在利用物联网的力量创造创新产品与服务。正因为这一转变&#xff0c;互联互通已成为我们生活中不可或缺的一部分&#xff0c;科技…

MVC入门(5)-- HttpMessageConverter 消息转换器

概念 HttpMessageConverter 是 Spring 框架中用于处理 HTTP 请求和响应数据的核心接口&#xff0c;负责在 Java 对象与 HTTP 消息体&#xff08;请求体或响应体&#xff09;之间进行双向转换。简单来说&#xff0c;它是 Spring 用来将 HTTP 请求中的原始数据&#xff08;如 JS…

Spark,连接MySQL数据库,添加数据,读取数据

以下是使用Spark连接MySQL数据库、添加数据和读取数据的步骤&#xff08;基于Scala API&#xff09;&#xff1a; 1. 准备工作 - 添加MySQL驱动依赖 在Spark项目中引入MySQL Connector JAR包&#xff08;如 mysql-connector-java-8.0.33.jar &#xff09;&#xff0c;或通过Sp…

关于 APK 反编译与重构工具集

一、apktool — APK 解包 / 重打包 apktool 是一款开源的 Android APK 工具&#xff0c;用于&#xff1a; 反编译 APK 查看资源和布局文件 生成 smali 文件&#xff08;DEX 的反汇编&#xff09; 对 APK 进行修改后重新打包 它不能还原 Java 源码&#xff0c;只能将 D…

[解决方案] Word转PDF

背景&#xff1a; 之前做过一些pdf导出&#xff0c; 客户提了一个特别急的需求&#xff0c; 要求根据一个模版跟一个csv的数据源&#xff0c; 批量生成PDF&#xff0c; 因为之前用过FOP&#xff0c; 知道调整样式需要特别长的时间&#xff0c; 这个需求又特别急&#xff0c; 所…

01 基本介绍及Pod基础

01 查看各种资源 01-1 查看K8s集群的内置资源 [rootmaster01 ~]# kubectl api-resources NAME SHORTNAMES APIVERSION NAMESPACED KIND bindings v1 …

19 C 语言位运算、赋值、条件、逗号运算符详解:涵盖运算符优先级与复杂表达式计算过程分析

1 位运算符 位运算符是对整数的二进制表示&#xff08;补码形式&#xff09;进行逐位操作的运算符。以下是主要的位运算符及其功能描述&#xff1a; 运算符描述操作数个数副作用&按位与2无|按位或2无^按位异或2无~按位取反1无<<按位左移2无>>按位右移2无 1.1…

哈希查找方法

已知哈希表长度为11&#xff0c;哈希函数为H&#xff08;key&#xff09;&#xff1d;key&#xff05;11&#xff0c;随机产生待散列的小于50的8个元素&#xff0c;同时采用线性探测再散列的方法处理冲突。任意输入要查找的数据&#xff0c;无论是否找到均给出提示信息。 int f…

JavaScript性能优化实战(10):前端框架性能优化深度解析

引言 React、Vue、Angular等框架虽然提供了强大的抽象和开发效率,但不恰当的使用方式会导致严重的性能问题,针对这些问题,本文将深入探讨前端框架性能优化的核心技术和最佳实践。 React性能优化核心技术 React通过虚拟DOM和高效的渲染机制提供了出色的性能,但当应用规模…

类和对象------2

目录 一. C面向对象模型初探1 .成员变量和函数的存储 二 this指针1 &#xff09;this指针工作原理2 &#xff09;this指针的使用3&#xff09; const修饰成员函数4 &#xff09;const修饰对象(常对象) 3.友元1 )友元语法2) 课堂练习 4 强化训练(数组类封装) 四 运算符重载&…

量子计算在金融科技中的应用前景

随着量子计算技术的飞速发展&#xff0c;其在各行业的应用潜力逐渐显现&#xff0c;金融科技领域更是备受关注。量子计算的强大计算能力有望为金融行业带来前所未有的变革&#xff0c;从风险评估到投资组合优化&#xff0c;从高频交易到加密技术&#xff0c;量子计算都可能成为…

Redisson 四大核心机制实现原理详解

一、可重入锁&#xff08;Reentrant Lock&#xff09; 可重入锁是什么&#xff1f; 通俗定义 可重入锁类似于一把“智能锁”&#xff0c;它能识别当前的锁持有者是否是当前线程&#xff1a; 如果是&#xff0c;则允许线程重复获取锁&#xff08;重入&#xff09;&#xff0c;并…

srs-7.0 支持obs推webrtc流

demo演示 官方教程: https://ossrs.net/lts/zh-cn/blog/Experience-Ultra-Low-Latency-Live-Streaming-with-OBS-WHIP 实现原理就是通过WHIP协议来传输 SDP信息 1、运行 ./objs/srs -c conf/rtc.conf 2、obs推流 3、web端播放webrtc流 打开web:ht

面试题——JDBC|Maven|Spring的IOC思想|DI思想|SpringMVC

目录 一、JDBC 1、jdbc连接数据库的基本步骤&#xff08;掌握**&#xff09; 2、Statement和PreparedStatement的区别 &#xff08;掌握***&#xff09; 二、Maven 1、maven的作用 2、maven 如何排除依赖 3、maven scope作用域有哪些&#xff1f; 三、Spring的IOC思想 …