Java玩转《啊哈算法》之模拟链表

人应该支配习惯,而绝不是让习惯支配人。一个人要是不能改掉坏习惯,那么他就一文不值。

目录

  • 代码地址
  • 模拟链表
    • 创建
    • 遍历打印
    • 插入
    • 插入优化
  • 完整代码

各位小伙伴们好呀!本人最近看了下《啊哈算法》,写的确实不错。

但稍显遗憾的是,书籍示例代码是c语言,而不是本人常用的Java。

那就弥补遗憾,说干就干,把这本书的示例语言用java写一遍, 顺带附上一些自己的理解!

今天这篇博客讲的是如何用数组来模拟链表。
在这里插入图片描述

来不及买纸质书但又想尽快感受算法魅力的童鞋也甭担心,电子版的下载链接已经放到下方了,可尽情下载。

链接:https://pan.baidu.com/s/1imxiElcCorw2F-HJEnB-PA?pwd=jmgs
提取码:jmgs

代码地址

本文代码已开源:

git clone https://gitee.com/guqueyue/my-blog-demo.git

请切换到gitee分支,

然后查看aHaAlgorithm模块下的src/main/java/com/guqueyue/aHaAlgorithm/chapter_2_StackAndChainTable即可!

模拟链表

在往期的博客中,我们用数组模拟了队列、栈,并且说了用链表也可以模拟队列、栈。

于是乎,我们还介绍了链表,但是链表指来指去的难免让人奇奇怪怪、晕头转向。

  1. Java玩转《啊哈算法》解密QQ号之队列
  2. Java玩转《啊哈算法》解密回文之栈
  3. Java玩转《啊哈算法》之链表

那么,这期博客,我们来讲一下如何用数组来模拟链表。

数组可以模拟队列、栈,链表也可以模拟队列、栈,数组也能模拟链表?没想到吧。

创建

那么,要怎么用数组来模拟链表呢?我们需要准备两个数组,一个数组存元素,一个数组用来存元素对应的下一个元素的位置
在这里插入图片描述
如上图所示,我们data数组用于存放元素内容,right数组用以存放相同索引处对应data数组的下一个元素的索引。

如图我们头节点的元素为data[1]也就是2,下一个元素为data[right[1]]也就是3。

当然,我们这里可以做一些小小的改动:

  1. 为了不浪费空间,我们的存放数组的索引从0开始而不是从1开始。
  2. 链表尾节点的下一个位置的索引,我们用-1表示,而不是0。

首先,我们声明一下需要使用的两个数组、链表的长度以便于录入数据以及控制台输入的对象:

   // 用于控制台输入private static Scanner scanner = new Scanner(System.in);private static int[] data = new int[101]; // 元素数组private static int[] right = new int[101]; // 索引数组private static int n = 0; // 链表长度

然后,我们就可以愉快的编写创建链表的方法了:

   /*** @Description 创建链表* @return void**/private static void createChainTable() {System.out.print("请输入数字个数: ");n = scanner.nextInt();System.out.printf("请输入%d个数,中间用空格隔开,输入完回车: ", n);for (int i = 0; i < n; i++) {data[i] = scanner.nextInt();}// 初始化right数组for (int i = 0; i < n; i++) {right[i] = i == n-1 ? -1 : i+1;}}

遍历打印

有了创建链表的方法,当然要有一个打印的方法,不然怎么验证:

  /*** @Description 打印链表* @return void**/private static void printChainTable() {// 输出int t = 0;System.out.print("链表为:" + data[t]);while(right[t] != -1) {t = right[t]; // 获取下一个元素的索引System.out.print("->" + data[t]);}System.out.println();}

ok了,下面让我们来验证一下:

package com.guqueyue.aHaAlgorithm.chapter_2_StackAndChainTable;import java.util.Scanner;/*** @Author: guqueyue* @Description: 用数组模拟链表* @Date: 2024/1/15**/
public class ChainTableTest2 {// 用于控制台输入private static Scanner scanner = new Scanner(System.in);private static int[] data = new int[101]; // 元素数组private static int[] right = new int[101]; // 索引数组private static int n = 0; // 链表长度public static void main(String[] args) {// 创建链表createChainTable();// 打印链表printChainTable();}/*** @Description 打印链表* @return void**/private static void printChainTable() {// 输出int t = 0;System.out.print("链表为:" + data[t]);while(right[t] != -1) {t = right[t]; // 获取下一个元素的索引System.out.print("->" + data[t]);}System.out.println();}/*** @Description 创建链表* @return void**/private static void createChainTable() {System.out.print("请输入数字个数: ");n = scanner.nextInt();System.out.printf("请输入%d个数,中间用空格隔开,输入完回车: ", n);for (int i = 0; i < n; i++) {data[i] = scanner.nextInt();}// 初始化right数组for (int i = 0; i < n; i++) {right[i] = i == n-1 ? -1 : i+1;}}
}

运行代码,控制台输入,可得:
在这里插入图片描述

插入

在这里插入图片描述

同样的,按照书上的逻辑,我们来写一个往链表中插入元素的方法:

   /*** @Description 插入链表* @return void**/private static void insertChainTable() {// 插入一个数int len = n;System.out.print("请输入插入的数:");data[len] = scanner.nextInt();// 按照链表顺序遍历 data 数组,找到比 num 大的数int t = 0;while (t != -1) {if (data[right[t]] > data[len]) { // 如果当前节点的下一个节点大于插入数,则插入right[len] = right[t]; // 插入的节点 指向当前节点的下一个节点right[t] = len; // 当前节点 指向插入的节点break;}t = right[t];}}

我们来验证一下(完整代码已开源,在本博客最后也可查看):

   public static void main(String[] args) {// 创建链表createChainTable();// 打印链表printChainTable();// 往链表中插入数据insertChainTable();// 打印链表printChainTable();}

运行,得:

在这里插入图片描述
看起来好像没啥问题,但是同上期博客一样,存在着两个问题:

  1. 如果插入的节点值大小小于头节点,该节点会被插入到头节点后面,违背了从小到大的顺序。
  2. 如果插入的节点值大于等于尾结点,则该节点不会被插入,甚至于直接报错!

如:
在这里插入图片描述
又比如:

在这里插入图片描述

插入优化

因此,我们来把插入方法优化一下,增加插入头节点和尾节点的逻辑:

	/*** @Description 按照从小到大的顺序插入链表* @return void**/private static void insertChainTable2() {// 插入一个数int len = n;System.out.print("请输入插入的数:");data[len] = scanner.nextInt();// 如果新插入的节点比 头节点 小,则插入到链表头部if (data[len] < data[0]) {// 头节点和尾节点互换int temp = data[0]; data[0] = data[len]; data[len] = temp;right[len] = right[0]; // 保持旧头节点原有的连接关系不变right[0] = len; // 将新的头节点指向旧的节点}else {// 按照链表顺序遍历 data 数组,找到比 num 大的数int t = 0;while (right[t] != -1) {if (data[right[t]] > data[len]) { // 如果当前节点的下一个节点大于插入数,则插入right[len] = right[t]; // 插入的节点 指向当前节点的下一个节点right[t] = len; // 当前节点 指向插入的节点break;}t = right[t];}// 插入的数如果比链表的最后一个节点大,则插入到链表尾部if (right[t] == -1) {right[n-1] = len;right[len] = -1;}}}

改动代码,来验证一下吧:

public static void main(String[] args) {// 创建链表createChainTable();// 打印链表printChainTable();// 往链表中插入数据
//        insertChainTable();insertChainTable2();// 打印链表printChainTable();
}

运行代码,分别验证,插入中间节点:

在这里插入图片描述
头节点:
在这里插入图片描述
尾节点:
在这里插入图片描述
很是完美!!!

完整代码

package com.guqueyue.aHaAlgorithm.chapter_2_StackAndChainTable;import java.util.Scanner;/*** @Author: guqueyue* @Description: 用数组模拟链表* @Date: 2024/1/15**/
public class ChainTableTest2 {// 用于控制台输入private static Scanner scanner = new Scanner(System.in);private static int[] data = new int[101]; // 元素数组private static int[] right = new int[101]; // 索引数组private static int n = 0; // 链表长度public static void main(String[] args) {// 创建链表createChainTable();// 打印链表printChainTable();// 往链表中插入数据
//        insertChainTable();insertChainTable2();// 打印链表printChainTable();}/*** @Description 打印链表* @return void**/private static void printChainTable() {// 输出int t = 0;System.out.print("链表为:" + data[t]);while(right[t] != -1) {t = right[t]; // 获取下一个元素的索引System.out.print("->" + data[t]);}System.out.println();}/*** @Description 插入链表* @return void**/private static void insertChainTable() {// 插入一个数int len = n;System.out.print("请输入插入的数:");data[len] = scanner.nextInt();// 按照链表顺序遍历 data 数组,找到比 num 大的数int t = 0;while (t != -1) {if (data[right[t]] > data[len]) { // 如果当前节点的下一个节点大于插入数,则插入right[len] = right[t]; // 插入的节点 指向当前节点的下一个节点right[t] = len; // 当前节点 指向插入的节点break;}t = right[t];}}/*** @Description 按照从小到大的顺序插入链表* @return void**/private static void insertChainTable2() {// 插入一个数int len = n;System.out.print("请输入插入的数:");data[len] = scanner.nextInt();// 如果新插入的节点比 头节点 小,则插入到链表头部if (data[len] < data[0]) {// 头节点和尾节点互换int temp = data[0]; data[0] = data[len]; data[len] = temp;right[len] = right[0]; // 保持旧头节点原有的连接关系不变right[0] = len; // 将新的头节点指向旧的节点}else {// 按照链表顺序遍历 data 数组,找到比 num 大的数int t = 0;while (right[t] != -1) {if (data[right[t]] > data[len]) { // 如果当前节点的下一个节点大于插入数,则插入right[len] = right[t]; // 插入的节点 指向当前节点的下一个节点right[t] = len; // 当前节点 指向插入的节点break;}t = right[t];}// 插入的数如果比链表的最后一个节点大,则插入到链表尾部if (right[t] == -1) {right[n-1] = len;right[len] = -1;}}}/*** @Description 创建链表* @return void**/private static void createChainTable() {System.out.print("请输入数字个数: ");n = scanner.nextInt();System.out.printf("请输入%d个数,中间用空格隔开,输入完回车: ", n);for (int i = 0; i < n; i++) {data[i] = scanner.nextInt();}// 初始化right数组for (int i = 0; i < n; i++) {right[i] = i == n-1 ? -1 : i+1;}}
}

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

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

相关文章

【C++】string 类 ( 上)

标准库中的string类 注意&#xff1a; 1. string是表示字符串的字符串类 2. 该类的接口与常规容器的接口基本相同&#xff0c;再添加了一些专门用来操作string的常规操作。 比特就业课 3. string在底层实际是&#xff1a;basic_string模板类的别名&#xff0c;typedef basi…

python爬虫之selenium知识点记录

selenium 一、前期准备 1、概述 selenium本身是一个自动化测试工具。它可以让python代码调用浏览器。并获取到浏览器中加载的各种资源。 我们可以利用selenium提供的各项功能。 帮助我们完成数据的抓取。 2、学习目标 掌握 selenium发送请求&#xff0c;加载网页的方法 掌…

Stable-Diffusion ubuntu服务器部署,报错解决方法(小白教程)

Stable Diffusion是一个深度学习模型&#xff0c;专注于生成高质量的图像。它由CompVis团队与Stability AI合作开发&#xff0c;并在2022年公开发布。这个模型使用文本提示&#xff08;text prompts&#xff09;生成详细、逼真的图像&#xff0c;是目前人工智能图像生成领域的一…

逆向案例四:360k静态和精灵数据动态AES解密,用js的方法

一、360K 网页链接:https://www.36kr.com/p/2672600261670407 页面中有静态的需要解密的内容&#xff0c;确定html包&#xff0c;确定方法 1.1方法步骤 在下方的搜索中输入decrypt(或者关键字window.initialState &#xff0c;进入js文件 在AES.decrypt处打上断点&#xff0…

机器学习-03-机器学习算法流程

总结 本系列是机器学习课程的第02篇&#xff0c;主要介绍机器学习中专家系统的应用介绍 本门课程的目标 完成一个特定行业的算法应用全过程&#xff1a; 定义问题&#xff08;Problem Definition&#xff09; -> 数据收集(Data Collection) -> 数据分割(Dataset Spit…

守护无价数据:文件备份的重要性与实用策略

一、数据安全&#xff1a;为何文件备份至关重要 在数字化时代&#xff0c;我们的生活和工作越来越离不开电子设备与其中的文件数据。这些文件可能包含重要的工作文档、珍贵的家庭照片、个人的创意作品等&#xff0c;它们是我们回忆的载体&#xff0c;也是我们工作和创新的基石…

PDF Expert for Mac v3.9.2中文激活版下载

PDF Expert for Mac是一款易于使用的 PDF 编辑器和注释器&#xff0c;专为 Mac 设备设计。它允许用户轻松查看、编辑、签名、注释和共享 PDF。该软件使用户能够向他们的 PDF 添加文本、图像、链接和形状&#xff0c;突出显示和标记文本&#xff0c;填写表格以及签署数字文档。它…

金融行业专题|期货超融合架构转型与场景探索合集(2023版)

更新内容&#xff1a; 更新 SmartX 超融合在期货行业的覆盖范围、部署规模与应用场景。新增 CTP 主席系统实践与评测、容器云资源池等场景实践。更多超融合金融核心生产业务场景实践&#xff0c;欢迎下载阅读电子书《SmartX 金融核心生产业务场景探索文章合集》。 面对不断变…

mac iNode 断开后没网 经测试 后台还在运行

界面断开&#xff0c;但是连不上网&#xff1a;实际上可能是服务在后台还在运行 解决方式&#xff1a;终端执行命令 &#xff0c;手动停止iNode服务 sudo /Library/StartupItems/iNodeAuthService/iNodeAuthService stop 停掉之后&#xff0c;有可能连不上网&#xff0c;断开wi…

基于springboot+vue的美食推荐商城

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

网工必懂的ICMP协议

福建厦门微思网络始于2002年&#xff0c;面向全国招生&#xff01; 主要课程&#xff1a;华为、思科、红帽、Oracle、VMware、CISP安全系列、PMP....... 网络工程师实用课程华为HCIA课程介绍 网络工程师使用课程华为HCIP课程介绍 网络工程师使用课程华为HCIE课程介绍 因特网…

更详细的软件测试理论基础:流程,开发、测试模型,测试分类,测试用例及其设计方法,缺陷

文章目录 一、测试流程二、开发模型1、 瀑布模型2、增量模型3、快速模型4、其他 三、测试模型1、V模型2、W模型 四、测试分类五、测试用例 test case六、测试用例设计方法1、等价类划分法2、边界值分析法3、因果图法4、判定表法5、正交法6、场景法7、流程分析法8、错误推测法方…

数据分析-Pandas数据的探查面积图

数据分析-Pandas数据的探查面积图 数据分析和处理中&#xff0c;难免会遇到各种数据&#xff0c;那么数据呈现怎样的规律呢&#xff1f;不管金融数据&#xff0c;风控数据&#xff0c;营销数据等等&#xff0c;莫不如此。如何通过图示展示数据的规律&#xff1f; 数据表&…

第16章-DNS

目录 1. 域名 1.1 产生背景 1.2 概述 1.3 域名的树形层次化结构 2. DNS 2.1 概述 2.2 工作机制 3. DNS查询模式 3.1 递归查询&#xff1a; 3.2 迭代查询&#xff1a; 4. 相关知识点 4.1 集中式DNS 4.2 国内通用DNS 4.3 配置DNS代理 1. 域名 1.1 产生背景 ① IP…

【Excel PDF 系列】iText 库直接实现表格 PDF

你知道的越多&#xff0c;你不知道的越多 点赞再看&#xff0c;养成习惯 如果您有疑问或者见解&#xff0c;欢迎指教&#xff1a; 企鹅&#xff1a;869192208 文章目录 前言生成表格 PDF 效果引入 pom 配置代码实现定义 CreateExcelToPdfModel 对象主方法 前言 最近遇到生成 E…

EchoServer回显服务器简单测试

目录 工具介绍 工具使用 测试结果 工具介绍 github的一个开源项目,是一个测压工具 EZLippi/WebBench: Webbench是Radim Kolar在1997年写的一个在linux下使用的非常简单的网站压测工具。它使用fork()模拟多个客户端同时访问我们设定的URL&#xff0c;测试网站在压力下工作的…

二维码门楼牌管理系统:城市数字化管理的新里程碑

文章目录 前言一、二维码门楼牌管理系统的构成二、二维码门楼牌管理系统的功能三、二维码门楼牌管理系统的应用四、二维码门楼牌管理系统的未来发展 前言 随着城市管理的数字化、智能化水平不断提升&#xff0c;二维码门楼牌管理系统作为一种创新的城市管理方法&#xff0c;正…

Ubuntu20.04: UE4.27 中 Source Code 的编辑器下拉框没有 Rider选项

问题描述 最近想用 Rider 作为 UE4 开发的 IDE&#xff0c;但安装好 Rider 后&#xff0c;发现编辑器下拉框中没有 Rider 的选项&#xff0c;我检查了 UE4 的插件&#xff0c;发现 Rider Integration 插件已经安装且启用的。 环境&#xff1a;Ubuntu 20.04 UE4.27 Rider2023…

应急加电电源车-在航空航天、武器等多领域的应用

应急加电电源车是一种专门设计用于在紧急情况下为其他设备提供电力支持的车辆。它通常由电池或燃料电池驱动&#xff0c;可以在没有外部电源的情况下为其他设备提供持续的电力供应。这种车辆在灾难救援、野外作业、军事行动等领域具有广泛的应用。 应急加电电源车通常具有以下…

WordPress建站入门教程:如何在本地电脑搭建WordPress网站?

前面跟大家分享了『WordPress建站入门教程&#xff1a;如何安装本地WordPress网站运行环境&#xff1f;』&#xff0c;接下来boke112百科就继续跟大家分享本地电脑如何搭建WordPress网站。 小皮面板&#xff08;phpstudy&#xff09;的“软件管理 – 网站程序”虽然可以一键部…