数组模拟双链表-java

news2024/11/19 17:50:22

通过数组来模拟双链表,并执行一些插入和删除的功能。

目录

一、问题描述

二、模拟思路

1.变量解释

2.数组初始化

3.在下标是k的结点后面插入一个结点

4.删除下标为k的结点

5.基本功能解释

三、代码如下

1.代码如下:

2.读入数据:

3.代码运行结果如下:

总结


前言

通过数组来模拟双链表,并执行一些插入和删除的功能。


一、问题描述

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

  1. 在最左侧插入一个数;
  2. 在最右侧插入一个数;
  3. 将第 k 个插入的数删除;
  4. 在第 k 个插入的数左侧插入一个数;
  5. 在第 k 个插入的数右侧插入一个数

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

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

输入格式

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

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

  1. L x,表示在链表的最左端插入数 x。
  2. R x,表示在链表的最右端插入数 x。
  3. D k,表示将第 k 个插入的数删除。
  4. IL k x,表示在第 k 个插入的数左侧插入一个数。
  5. IR k x,表示在第 k个插入的数右侧插入一个数。

输出格式

共一行,将整个链表从左到右输出。

数据范围

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

二、模拟思路

1.变量解释

 图1.1样例图

我们引入一维整型数组e,用来存储结点的值;一维整型数组l,用来记录当前结点指向左边结点的索引值;一维整型数组r,用来记录当前结点指向的右边结点的索引值;整型变量index用来表示数组e中第一个空结点的索引值,即创建新结点的索引值。

2.数组初始化

图2.1样例图 

 我们进行初始化操作将索引0和索引1的结点直接占用,分别表示头结点和尾结点,让头结点的右指针指向尾结点,然后让尾结点的左指针指向头结点,第一个空结点从索引为2的结点开始。

    //初始化
    public static void init(){
        r[0] = 1;
        l[1] = 0;
        index = 2;
    }

3.在下标是k的结点后面插入一个结点

图3.1 

 我们传入下标k和结点的值x,我们先让结点存入链表,即e[index] = x。然后我们需要让新插入的结点的右指针指向下标为k指向的右节点;新插入的结点的右指针为r[index],下标为k的结点指向的右节点为r[k],即r[index] = r[k];让新插入的结点的左指针指向下标为k的结点即l[index] = k;让下标为k的结点指向的右结点的左指针指向新插入的结点,让下标为k的结点指向的右结点的左指针为l[r[k]],即l[r[k]] = index;再让下标为k的结点指向的右指针指向新结点即r[k] = index;此时我们就完成了将新结点插入整个链表。切记因为进行这一系列操作我们需要记录下标为k的结点的下一个结点即r[k],如果我们先修改这个值,那么后面再用就会发生变化,所以要么用变量先存储,要么r[k]我们先用,修改的操作最后进行,这样不容易发生错误。

最后将index++,让index一直保持是第一个空结点的下标。

4.删除下标为k的结点

图4.1思路模拟 

我们删除下标为k的结点 ,即直接让下标为k的前一个结点的右指针指向下标为k的结点的后一个结点,让下标为k的结点的后一个结点的左指针指向下标为k的的结点的前一个结点即可。下标为k的前一个结点为l[k],下标为k的后一个结点为r[k],我们完场上述两个操作是r[l[k]] = r[k]、l[r[k]] = l[k],这样我们就完成了删除下标为k的结点的操作。

    //删除下标为k的结点
    public static void delete(int k){
        r[l[k]] = r[k];
        l[r[k]] = l[k];
    }

5.基本功能解释

 在最左则插入一个结点就是在下标为0的点的右边插入一个结点,即是add(0,x);在最右侧添加一个结点就是在尾结点的前一个结点的后面添加一个结点,即add(l[1],x);将第 k 个插入的结点删除,我们第1个插入的结点是在索引2的位置,那么我们第k个插入的结点就是在索引为k+1的位置,那么该操作为delete(k+1);在第 k 个插入的数左侧插入一个结点,即是在下标为k+1的左边的结点的后面插入一个数即add(l[k+1],x);在第 k个插入的数右侧插入一个结点,就直接在下标为k+1的结点后面插入一个结点即add(k+1,x)。

三、代码如下

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 = 100010;
    //存储结点的值
    static int[] e = new int[N];
    //存储结点连接的左节点索引
    static int[] l = new int[N];
    //存储结点连接的右节点索引
    static int[] r = new int[N];
    //数组e中第一个空结点的索引
    static int index;
    public static void main(String[] args) {
        Scanner sc = new Scanner(br);
        int m = Integer.parseInt(sc.nextLine());
        init();
        while (m-- > 0){
            String[] str = sc.nextLine().split(" ");
            String cmd = str[0];
            int k,x;
            //最左边插入,即在下标为0的结点右边插入
            if(cmd.equals("L")){
                x = Integer.parseInt(str[1]);
                add(0,x);
            }
            //最右边插入,即尾结点1的左指针指向的结点的右边插入
            else if (cmd.equals("R")) {
                x = Integer.parseInt(str[1]);
                add(l[1],x);
            }
            else if (cmd.equals("D")) {
                k = Integer.parseInt(str[1]);
                delete(k+1);
            } else if (cmd.equals("IL")) {
                k = Integer.parseInt(str[1]);
                x = Integer.parseInt(str[2]);
                add(l[k+1],x);
            }else if(cmd.equals("IR")) {
                k = Integer.parseInt(str[1]);
                x = Integer.parseInt(str[2]);
                add(k+1,x);
            }
        }
        for(int i = r[0];i !=1;i = r[i]){
            pw.print(e[i]+" ");
        }
        pw.flush();
    }
    //初始化
    public static void init(){
        r[0] = 1;
        l[1] = 0;
        index = 2;
    }
    //在下标是k的右边插入一个点
    public static void add(int k,int x){
        e[index] = x;
        r[index] = r[k];
        l[index] = k;
        l[r[k]] = index;
        r[k] = index;
        index++;
    }
    //删除下标为k的结点
    public static void delete(int k){
        r[l[k]] = r[k];
        l[r[k]] = l[k];
    }
}

2.读入数据:

10
R 7
D 1
L 3
IL 2 10
D 3
IL 2 7
L 8
R 9
IL 4 7
IR 2 2

3.代码运行结果如下:

8 7 7 3 2 9

总结

当我们刷算法题时可以通过数组来模拟链表,比直接用结构体的代码会简洁一点。

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

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

相关文章

VSCode 配置 CMake

VSCode 配置 C/C 环境的详细过程可参考:VSCode 配置 C/C 环境 1 配置C/C编译环境 方案一 如果是在Windows,需要安装 MingW,可以去官网(https://sourceforge.net/projects/mingw-w64/)下载安装包。 注意安装路径不要出现中文。 打开 windows…

【LocalAI】(10):在autodl上编译embeddings.cpp项目,转换bge-base-zh-v1.5模型成ggml格式,本地运行main成功

1,关于 localai LocalAI 是一个用于本地推理的,与 OpenAI API 规范兼容的 REST API。 它允许您在本地使用消费级硬件运行 LLM(不仅如此),支持与 ggml 格式兼容的多个模型系列。支持CPU硬件/GPU硬件。 【LocalAI】&…

【算法小白周赛1A】分析 - 题解与代码

题目链接:https://www.starrycoding.com/problem/155 题目描述 小可可最近在学数学运算!他希望考考你,给你两个整数 A , B A,B A,B,询问 A B A\times B AB 是否是偶数。 注意,可能存在前导 0 0 0,比如…

【C++】:日期类的实现 -- 日期计算器

前言 1.日期类是一种十分经典的类型。对于C的初学者,它能够帮助我们融会贯通许多C的基础知识,它涉及许多的基础语法,比如引用,函数重载,传值/传参返回,构造函数,运算符重载,const成…

Python 与 TensorFlow2 生成式 AI(五)

原文:zh.annas-archive.org/md5/d06d282ea0d9c23c57f0ce31225acf76 译者:飞龙 协议:CC BY-NC-SA 4.0 第十二章:用生成式人工智能玩视频游戏:GAIL 在之前的章节中,我们已经看到如何使用生成式人工智能来生成…

如何在Linux上安装Python?2024Python安装教程

在Linux上安装Python并不难,对于Ubuntu或Debian系统,使用命令sudo apt install python3;对于CentOS、Red Hat或Fedora系统,使用命令sudo yum install python3。 如何在Linux上安装Python? 确切的安装步骤有所不同&am…

Django后台项目开发实战七

为后台管理系统换风格 第七阶段 安装皮肤包 pip install django-grappelli 在 setting.py 注册 INSTALLED_APPS [grappelli,django.contrib.admin,django.contrib.auth,django.contrib.contenttypes,django.contrib.sessions,django.contrib.messages,django.contrib.stat…

微隔离实施五步法,让安全防护转起来

前言 零信任的最核心原则→最小权限 安全的第一性原理→预防 零信任的最佳实践→微隔离 “零信任”这个术语的正式出现,公认是在2010年由Forrester分析师John Kindervag最早提出。时至今日,“零信任”俨然已成安全领域最热门的词汇,做安全…

如何使用Go语言进行并发安全的数据访问?

文章目录 并发安全问题的原因解决方案1. 使用互斥锁(Mutex)示例代码: 2. 使用原子操作(Atomic Operations)示例代码: 3. 使用通道(Channels) 在Go语言中,进行并发编程是常…

《QT实用小工具·四十九》QT开发的轮播图

1、概述 源码放在文章末尾 该项目实现了界面轮播图的效果,包含如下特点: 左右轮播 鼠标悬浮切换,无需点击 自动定时轮播 自动裁剪和缩放不同尺寸图片 任意添加、插入、删除 单击事件,支持索引和自定义文本 界面美观,圆…

遥感雷达波段的原理及应用

雷达波段是不同波长的组。每一种都有其独特的穿透地球表面的能力。它们还可以揭示环境的不同方面。 雷达频段在电磁频谱内具有特定的频率范围。这些波段由 L-、S-、C- 和 X-波段等字母表示。稍后会详细介绍这一点。 什么是合成孔径雷达? 合成孔径雷达 (SAR) 是一…

C语言实验-循环结构和选择结构

一&#xff1a; 求和:1(14)(149)(14916)…(14916…n2)? 其中n的值由键盘输入&#xff1b; #define _CRT_SECURE_NO_WARNINGS #include<stdio.h>int main() {int sum 0;int n 0;printf("请输入一个整数");scanf("%d", &n);for (int i 0; i &l…

MATLAB 字符串

MATLAB 字符串 在MATLAB中创建字符串非常简单。实际上&#xff0c;我们已经使用了很多次。例如&#xff0c;您在命令提示符下键入以下内容- 示例 my_string ‘(cainiaojc.com)’ MATLAB将执行上述语句并返回以下结果 my_string (cainiaojc.com) MATLAB将所有变量视为数组&a…

Python基础学习之记录中间文件

倘若想记录代码运行过程中的结果文件&#xff0c;那么以下函数仅供参考 代码示例&#xff1a; import os import datetime import sys import pandas as pd# 定义总的文件夹路径 base_folder E:\\D\\log\\product_data_compare_log# 定义一个函数来创建带时间戳的文件夹 def…

特征提取(Feature Extraction)常见统计特征笔记(三)

统计特征是描述数据集中值的一组量&#xff0c;通常用于了解数据的分布、集中趋势和变异程度。常见的统计特征包括均值、中位数、众数、标准差、方差等。下面会详细解释每个统计特征&#xff0c;并给出相应的Python代码。 1、均值&#xff08;Mean&#xff09;&#xff1a;所有…

【团体程序设计天梯赛】往年关键真题 L2-036 网红点打卡攻略 模拟 L2-037 包装机 栈和队列 详细分析完整AC代码

【团体程序设计天梯赛 往年关键真题 详细分析&完整AC代码】搞懂了赛场上拿下就稳 【团体程序设计天梯赛 往年关键真题 25分题合集 详细分析&完整AC代码】&#xff08;L2-001 - L2-024&#xff09;搞懂了赛场上拿下就稳了 【团体程序设计天梯赛 往年关键真题 25分题合…

【webrtc】MessageHandler 4: 基于线程的消息处理:以Fake 收发包模拟为例

G:\CDN\rtcCli\m98\src\media\base\fake_network_interface.h// Fake NetworkInterface that sends/receives RTP/RTCP packets.虚假的网络接口,用于模拟发送包、接收包单纯仅是处理一个ST_RTP包 消息的id就是ST_RTP 类型,– 然后给到目的地:mediachannel处理: 最后消息消…

沟通是SAP项目成功的关键

我在前面的文章中提到SAP项目并不是传统意义上的IT项目&#xff0c;因为SAP项目实施的不仅仅是一个简单的ERP系统&#xff0c;除了系统之外还有流程再造、组织结构变更、用户培训等。在实施过程中有很多部门都要参与进来讨论和做决定&#xff0c;有很多问题和冲突需要解决。从关…

LangChain入门2 RAG详解

RAG概述 一个典型的RAG应用程序,它有两个主要组件&#xff1a; 索引&#xff1a;从源中获取数据并对其进行索引的管道。这通常在脱机情况下发生。检索和生成&#xff1a;在运行时接受用户查询&#xff0c;并从索引中检索相关数据&#xff0c;然后将其传递给模型。 从原始数据…

透明加密的解释及意义,透明加密软件有哪些?

一、什么是透明加密及意义 透明数据加密&#xff08;Transparent Data Encryption (简称TDE)&#xff09;是指可以在文件层对数据和文件进行实时加密和解密&#xff0c;落盘的文件是加密后的内容&#xff0c;而对于上层应用系统和开发人员而言&#xff0c;加解密过程是无感知的…