单链表-java

此次我们主要通过数组来模拟一下单链表,并完成一些基本的功能。

文章目录

前言

一、单链表

二、思路模拟

1.引入变量解释

2.链表初始化

3.在头结点后插入一个结点

4.表示在第k个数后面插入一个数

5. 把第k个数后面的一个数删除掉

三、代码如下

1.代码如下:

2.读入数据

3.代码运行结果

总结


前言

此次我们主要通过数组来模拟一下单链表,并完成一些基本的功能。


一、单链表

实现一个单链表,链表初始为空,支持三种操作:

  1. 向链表头插入一个数;
  2. 删除第 k 个插入的数后面的一个数;
  3. 在第 k个插入的数后插入一个数。

现在要对该链表进行 M次操作,进行完所有操作后,从头到尾输出整个链表。

注意:题目中第 k个插入的数并不是指当前链表的第 k 个数。例如操作过程中一共插入了 n 个数,则按照插入的时间顺序,这 n个数依次为:第 1个插入的数,第 2个插入的数,…第 n个插入的数。

输入格式

第一行包含整数 M,表示操作次数。

接下来 M 行,每行包含一个操作命令,操作命令可能为以下几种:

  1. H x,表示向链表头插入一个数 x。
  2. D k,表示删除第 k 个插入的数后面的数(当 k 为 00 时,表示删除头结点)。
  3. I k x,表示在第 k 个插入的数后面插入一个数 x(此操作中 k 均大于 00)。

输出格式

共一行,将整个链表从头到尾输出。

数据范围

1≤M≤100000
所有操作保证合法。

二、思路模拟

1.引入变量解释

图1.1 数组模拟单链表

我们引入一个整型head,来表示头结点(第一个结点)的下标;引入一维整型数组e,用来存储结点的值;一个整型index,用来表示当前数组e第一个没有存储值的下标(即第一个空结点的下标),或者是我们新存入结点,index就是新存入结点在e数组的下标;用一个一维整型数组ne,用来存储当前结点指向的下一个结点(假设3结点指向5结点)即5结点在数组e中的下标(如图1.1)。

2.链表初始化

head的初始值为-1,此时表示该链表为空,没有存储任何值;

index的初始值为0,表示空链表,即第一个结点就是空的。

    //初始化public static void init(){head = -1;index = 0;}

3.在头结点后插入一个结点

图3.1思路模拟 

我们新插入的结点值是x,那么我们先创建一个结点即e[index] = x;然后我们需要将新结点指向头结点原本指向的结点,原本头结点的下标就是head,而ne[index]就是新结点要指向下一个结点的下标,那么我们要进行即ne[index] = head;然后我们要让头指针指向新结点,即head = index,即此时的头结点的下标就是我们新插入结点的下标。最后切记index++,因为我们index表示的是在e数组中第一个空的结点的下标,那么我们用了一个结点,我们就是让index后移一位,让index指向的结点仍是空的。

    //将x插入头结点后面public static void addHead(int x){e[index] = x;ne[index] = head;head = index;index++;}

4.表示在第k个数后面插入一个数

图4.1思路模拟 

这个操作我们可以转换成在指定下标的结点后面插入一个结点的操作。(注意图中的k是结点的下标)我们将新插入的结点赋值为x即e[index] = x,然后我们需要让新结点指向下标为k的结点指向的下一个结点,此时下标为k的结点指向的下一个结点就是ne[k],那么我们需要进行e[index] = ne[k],此时我们新结点就指向原本下标为k结点所指向的下一个结点。最后我们还要让下标为k的结点指向新结点,下标为k的结点指向的下一个结点的下标为ne[k],那么我们就需要让ne[k] = index,此时我们就完成了将新结点插入整个链表。最后切记让index++,还是为了index指向的结点仍是空的。

    //将x插入到下标是k的结点后面public static void add(int x,int k){e[index] = x;ne[index] = ne[k];ne[k] = index;index++;}

5. 把第k个数后面的一个数删除掉

图5.1思路模拟 

我们可以转化为删除指定下标结点的后面一个结点。假设我们要删除下标为k的结点的后面一个结点,那么我们需要让结点k指向它的下一个结点指向的下一个结点,结点k指向的下一个结点为ne[k],我们假设这个结点的下标为m,那么m = ne[k]。然后m指向的下一个结点为ne[m]。我们的删除操作就是让结点k直接指向m指向的下一个结点,即ne[k] = ne[m],最后我们可以写成ne[k] = ne[ne[k]]。此时我们就完成了删除操作。

    //将下标为k的结点后面的结点删掉public static void remove(int k){ne[k] = ne[ne[k]];}

当我们删除第0个插入的数后面一个数,传入的下标k = 0 - 1发生数组越界,我们需要特殊处理一下 ,即删除头节点,那我们就需要将头指针后移,就是将头结点的索引head,改为头结点的下一个结点即ne[head],那么我们进行head = ne[head]即可。

            //删除下标为k-1结点的后一个结点else if (cmd.equals("D")) {k = Integer.parseInt(str[1]);if(k != 0){remove(k-1);}//表示删除头结点,头指针后移else {head = ne[head];}}

注:当这个结点的下一个结点的索引是-1时,就说明这就是最后一个结点。 

三、代码如下

1.代码如下:


import java.io.*;
import java.util.*;public class 单链表 {static PrintWriter pw = new PrintWriter(new OutputStreamWriter(System.out));static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));static int N = 1000010;//表示第一个结点的下标static int head;//存储结点值static int[] e = new int[N];//存储下一个结点的下标static int[]ne = new int[N];//指针,e数组最新空的元素的下标static int index;public static void main(String[] args) {Scanner sc = new Scanner(br);init();int m = Integer.parseInt(sc.nextLine());while (m-- > 0){int k,x;String[] str = sc.nextLine().split(" ");String cmd = str[0];//向链表头插入一个结点if(cmd.equals("H")){x = Integer.parseInt(str[1]);addHead(x);}//删除下标为k-1结点的后一个结点else if (cmd.equals("D")) {k = Integer.parseInt(str[1]);if(k != 0){remove(k-1);}//表示删除头结点,头指针后移else {head = ne[head];}}//在下标为k-1的结点后面插一个结点else if (cmd.equals("I")) {k = Integer.parseInt(str[1]);x = Integer.parseInt(str[2]);add(k-1,x);}}//打印链表for(int i = head;i != -1;i = ne[i]){pw.print(e[i]+" ");}pw.flush();}//初始化public static void init(){head = -1;index = 0;}//将x插入头结点后面public static void addHead(int x){e[index] = x;ne[index] = head;head = index;index++;}//将x插入到下标是k的结点后面public static void add(int k,int x){e[index] = x;ne[index] = ne[k];ne[k] = index;index++;}//将下标为k的结点后面的结点删掉public static void remove(int k){ne[k] = ne[ne[k]];}
}

2.读入数据

10
H 9
I 1 1
D 1
D 0
H 6
I 3 6
I 4 5
I 4 5
I 3 4
D 6

3.代码运行结果

6 4 6 5 

总结

上午主要通过数组来模拟单链表,关键通过对各个变量知道什么意思,明白增删操作是怎样进行的,看一下图示和文字描述加强一下理解。

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

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

相关文章

NDK 入门(二)—— 调音小项目

NDK 入门系列主要介绍 JNI 的相关内容,目录如下: NDK 入门(一)—— JNI 初探 NDK 入门(二)—— 调音小项目 NDK 入门(三)—— JNI 注册与 JNI 线程 NDK 入门(四&#xff…

数字滤波器设计笔记1

系统结构 1.先利用matlab的simulink和FDA进行滤波器建模设计,通过仿真后,确定模型达到相应的性能要求,再利用verilog进行电路设计。最后使用modelsim进行功能验证。其中testbench的输入数据,利用matlab模型的输入数据。 2.Matlab…

IOS 设置UIButton按钮的选中状态样式

设置按钮的边框 self.titleBtn.backgroundColor UIColor.whiteColor;self.titleBtn.layer.borderColor [UIColor colorWithHexString:"#B3B3B3" withAlpha:0.3].CGColor;self.titleBtn.layer.borderWidth 0.5;self.titleBtn.clipsToBounds YES;self.titleBtn.hei…

SQL Server的基本操作示例

我可以为您提供一些SQL Server的基本操作示例。以下是增删改查的简单示例: 增加数据: INSERT INTO 表名 (列1, 列2, 列3) VALUES (值1, 值2, 值3);示例: INSERT INTO Employees (FirstName, LastName, Age) VALUES (John, Doe, 30);删除数…

最最普通程序员,如何利用工资攒够彩礼,成为人生赢家

今天我们不讲如何提升你的专业技能去涨工资,不讲面试技巧如何跳槽涨工资,不讲如何干兼职赚人生第一桶金,就讲一个最最普通的程序员,如何在工作几年后,可以攒够彩礼钱,婚礼酒席钱,在自己人生大事…

Flutter 之PopScope组件的基本用法,拦截系统返回键

Flutter中提供了PopScope组件替代了原来的WillPopScope组件,PopScope组件的作用就是管理系统的返回操作: Manages system back gestures.,该组件提供给来三个参数: const PopScope({super.key,required this.child,//布局Widgetthis.canPop = true,this

Oracle用户授权的一些知识点

Oracle用户授权的一些知识点 常见用户授权场景跨模式授权的场景常见用户授权场景 数据库对象创建权限修改权限删除权限执行权限Procedure(存储过程)CREATE PROCEDURE 或 CREATE ANY PROCEDURE自己SCHEMA内无需额外授权;或 ALTER ANY PROCEDURE自己SCHEMA内无需额外授权;或 …

pytho爬取南京房源成交价信息并导入到excel

# encoding: utf-8 # File_name: import requests from bs4 import BeautifulSoup import xlrd #导入xlrd库 import pandas as pd import openpyxl# 定义函数来获取南京最新的二手房房子成交价 def get_nanjing_latest_second_hand_prices():cookies {select_city: 320100,li…

信息系统项目管理师——第5章信息系统工程(一)

近几期的考情来看,本章选择题稳定考4分,考案例的可能性有,需要重点学习。本章节专业知识点特别多。但是,只考课本原话,大家一定要把本章至少通读一遍,还要多刷题,巩固重点知识。 1 软件工程 软…

deepin 开源之夏重磅来袭!超优质项目已上线,欢迎来战

内容来源:deepin 社区 「开源之夏」是由中国科学院软件研究所“开源软件供应链点亮计划”发起并长期支持的一项暑期开源活动,旨在鼓励在校学生积极参与开源软件的开发维护,培养和发掘更多优秀的开发者,促进优秀开源软件社区的蓬勃…

Java实现二叉树(简单版)

1.先定义节点 /*定义一个树节点*/ public class TreeNode {int val; //存储值TreeNode left; //左子树TreeNode right; //右子树//无参构造方法TreeNode (){}//有参构造方法TreeNode(int val){this.valval;}TreeNode(int val,TreeNode left,TreeNode right){this.v…

简单实现日期计算器

目录&#xff1a; Date.h实现函数声明Date.c实现函数功能 构造函数六个比较函数日期 天数日期 - 天数日期 - 日期操作符操作符--获取每月的天数 &#x1f698;正片开始 Date.h头文件中实现函数声明 #pragma once #include<iostream> using namespace std; class Dat…

javamail发送qq邮箱失败案例分析

文章目录 javaMail报错:Unsupported or unrecognized SSL message原因分析: ssl与tls端口总结 javaMail报错:Unsupported or unrecognized SSL message c.n.m.service.impl.EmailServiceImpl : 邮件发送异常, Mail server connection failed; nested exception is javax.m…

SqlSessionFactory

在Java中&#xff0c;SqlSessionFactory是MyBatis框架中的一个重要类&#xff0c;它用于创建SqlSession对象。SqlSession是MyBatis框架中用于执行SQL语句的主要对象&#xff0c;它提供了对数据库操作的各种方法。 SqlSessionFactory的主要作用是创建SqlSession对象&#xff0c…

Linux 解压报错

在linux上面解压压缩包&#xff0c;有可能遇到一下问题&#xff0c;现提供正确语句供参考 一、tar命令解压.zip文件 在使用tar命令解压.zip格式文件时&#xff0c;有时会遇到一下异常 gzip: stdin has more than one entry--rest ignored tar: Child returned status 2 ta…

Spring AI 来啦,快速上手

Spring AI Spring框架在软件开发领域&#xff0c;特别是在Java企业级应用中&#xff0c;一直扮演着举足轻重的角色。它以其强大的功能和灵活的架构&#xff0c;帮助开发者高效构建复杂的应用程序。而Spring Boot的推出&#xff0c;更是简化了新Spring应用的初始搭建和开发过程…

【分治算法】【Python实现】棋盘覆盖

文章目录 [toc]问题描述分治算法时间复杂性Python实现 个人主页&#xff1a;丷从心 系列专栏&#xff1a;分治算法 学习指南&#xff1a;Python学习指南 问题描述 在一个 2 k 2 k 2^{k} \times 2^{k} 2k2k个方格组成的棋盘中&#xff0c;若恰有一个方格与其他方格不同&…

httpClient提交报文中文乱码

httpClient提交中文乱码&#xff0c;ContentType类型application/json 指定提交参数的编码即可 StringEntity se new StringEntity(paramBody.toJSONString(),"UTF-8");se.setContentType("application/json");context.httpPost.setHeader("Cookie&…

【算法模版】基础算法

文章目录 快速排序算法模板归并排序算法模板整数二分算法模板浮点数二分算法模板高精度加法、减法、乘法、除法高精度加法高精度减法高精度乘低精度高精度除以低精度前缀和与差分一维前缀和二维前缀和一维差分二维差分位运算双指针算法离散化区间合并 快速排序算法模板 快速排…

JUC并发-共享模型-无锁-乐观锁(非阻塞)

1、问题提出 有如下需求&#xff0c;保证 account.withdraw 取款方法的线程安全 public class TestAccount {public static void main(String[] args) {Account account new AccountCas(10000);Account.demo(account);} }class AccountUnsafe implements Account {private I…