双链表——AcWing.827双链表

news2024/11/24 2:19:20

双链表

定义

双链表是链表的一种,它的每个节点有两个指针,一个指向前一个节点,一个指向后一个节点。这样使得链表可以双向遍历。

运用情况

  • 频繁进行前后双向遍历操作时非常有用,比如在一些需要来回移动处理数据的场景。
  • 可以方便地实现诸如栈、队列等数据结构的混合操作。
  • 在一些需要快速插入和删除节点,同时又需要双向遍历的特定算法和程序中经常被采用。

注意事项

  • 内存管理要恰当,确保正确地分配和释放节点内存,避免内存泄漏或非法访问。
  • 对节点指针的操作要格外小心,防止出现悬空指针或错误指向。
  • 在进行插入、删除等操作时,要注意前后节点指针的正确更新,保持链表的完整性。

解题思路

当使用双链表解决问题时,一般思路如下:

  • 明确问题中涉及到的操作,比如插入、删除、遍历等。
  • 根据操作确定如何更新节点的前后指针以维持链表结构。
  • 在进行复杂操作时,仔细考虑边界情况和特殊情况,确保算法的正确性和鲁棒性。
  • 可以借助一些辅助指针或变量来方便地进行节点的定位和操作。例如,在寻找特定节点时,可以利用前后向的遍历。
  • 对于一些需要高效操作的场景,优化指针的操作顺序和算法流程以提高性能。

AcWing.827双链表

题目描述

827. 双链表 - AcWing题库

运行代码

#include <iostream>
using namespace std;
const int N = 100010;
int l[N], r[N], idx, e[N];
int n;
void init()
{
    r[0] = 1, l[1] = 0, idx = 2;
}
void insert(int k, int x)
{
    e[idx] = x;
    l[idx] = k, r[idx] = r[k];
    l[r[k]] = idx, r[k] = idx ++ ;
}
void Remove(int k)
{
    l[r[k]] = l[k];
    r[l[k]] = r[k];
}
int main()
{
    init();
    cin >> n;
    while(n -- )
    {
        string op;
        int k, x;
        cin >> op;
        if(op == "L")
        {
            cin >> x;
            insert(0, x);
        }
        else if(op == "R")
        {
            cin >> x;
            insert(l[1], x);
        }
        else if(op == "IL")
        {
            cin >> k >> x;
            insert(l[k + 1], x);
        }
        else if(op == "IR")
        {
            cin >> k >> x;
            insert(k + 1, x);
        }
        else 
        {
            cin >> k;
            Remove(k + 1);
        }
    }
    for(int i = r[0]; i != 1; i = r[i]) cout << e[i] << ' ';    
    return 0;
}

代码思路

  1. 初始化:
    • 使用两个数组lr来分别存储每个节点的左指针和右指针。
    • 数组e用于存储每个节点的值。
    • idx用于追踪下一个要插入的节点的索引。
    • init()函数初始化双链表,将第一个虚拟节点(通常用作头节点)的右指针指向第二个虚拟节点(通常用作尾节点的前一个节点),并将第二个虚拟节点的左指针指向第一个虚拟节点。
  2. 插入操作:
    • insert(int k, int x)函数用于在给定节点k的右侧插入一个新节点,其值为x
    • 首先,将新节点的值存储在e[idx]中。
    • 然后,更新l[idx]r[idx]以指向正确的邻居节点。
    • 同时,更新k的右邻居和idx的左邻居的指针,使其指向新节点。
    • 最后,递增idx以准备下一次插入。
  3. 删除操作:
    • Remove(int k)函数用于删除给定节点k(注意:这里的k是节点在数组中的索引,而不是节点值)。
    • 通过更新k的左邻居的右指针和k的右邻居的左指针,来删除节点k
    • 注意:这里没有显式地释放或重置数组e中的值,因为C++的数组不会自动管理内存。但由于e是静态分配的,它将在程序结束时自动被销毁。
  4. 主函数:
    • 读取一个整数n,表示将要进行的操作数。
    • 对于每个操作,读取一个操作码op和一个或两个参数(取决于操作)。
    • 根据操作码执行相应的操作:
      • "L": 在双链表的左侧插入一个新节点。
      • "R": 在双链表的右侧插入一个新节点。
      • "IL": 在第k个节点的左侧插入一个新节点。
      • "IR": 在第k个节点的右侧插入一个新节点。
      • 其他: 删除第k个节点。
    • 在所有操作完成后,遍历并打印双链表中的节点值。

注意

  • 这里的节点索引是从虚拟头节点(索引为0)和虚拟尾节点的前一个节点(索引为1)开始的。因此,当插入或删除节点时,需要使用k + 1来引用实际的节点索引(从2开始)。
  • 代码没有包含错误检查,例如检查k是否超出了链表的合法范围。在实际应用中,应添加这些检查以防止程序崩溃或产生不可预测的行为。

改进思路

  1. 添加错误处理
    • 在进行插入或删除操作时,检查给定的索引k是否在链表的有效范围内。
    • 检查操作是否符合预期,比如尝试在已经不存在的节点上进行操作。
  2. 使用结构体或类
    • 创建一个结构体或类来表示链表节点,这样可以使代码更加清晰,并减少错误的可能性。
    • 在这个结构体或类中,可以包含节点的值、左指针和右指针。
  3. 封装链表操作
    • 将链表的操作(如插入、删除、遍历等)封装到类的方法中,这样可以使代码更加模块化。
    • 封装后的代码可以提供更好的封装性、继承性和多态性。
  4. 使用迭代器或指针
    • 考虑使用迭代器或指针来遍历链表,而不是直接使用数组索引。这可以使代码更加灵活,并减少错误的可能性。
  5. 改进输入验证
    • main函数中,添加对输入数据的验证,确保输入的操作码和参数是有效的。
    • 可以使用std::cin.fail()或类似的函数来检查输入是否成功。
  6. 使用标准库容器
    • 如果可能的话,考虑使用C++标准库中的容器(如std::list)来实现链表。这样可以减少手动管理内存和指针的复杂性,并提高代码的可读性和可维护性。
  7. 改进遍历打印逻辑
    • 遍历链表时,可以使用循环而不是递归,以提高效率。
    • 在打印链表时,可以添加一些分隔符或换行符,使输出更加清晰。
  8. 优化内存使用
    • 如果链表中的节点数量非常大,可以考虑使用动态内存分配来减少内存使用。
    • 但是,请注意,动态内存分配也会增加内存泄漏和指针错误的风险。
  9. 添加注释和文档:为代码添加注释,解释每个函数、类和变量的作用。编写文档,描述如何使用这个链表类,以及它的特性和限制。
  10. 使用异常处理:如果在链表操作中发生错误(如无效索引、无效操作等),可以使用C++的异常处理机制来抛出异常,并在调用者处捕获和处理这些异常。这可以使错误处理更加清晰和一致。

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

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

相关文章

【Linux系列】深入理解 CURL 命令及其在网络请求中的应用

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

用宝塔部署vue+springboot上线公网详细步骤

首先自己在腾讯云中按照教程安装好宝塔。这是宝塔面板&#xff0c;获取登录宝塔的网址和账号密码。 1.在navicat新建数据库 如果出现权限问题&#xff0c;可以在宝塔数据库面板phpMyAdmin中进行权限设置 navicat可以修改用户权限 2.在宝塔面板新建数据库 3.将前端打包的dist文件…

k8s部署短视频网站(后台+web前端+web管理)

一、系统环境 系统centos7k8sv1.24containerdv1.7.16etcdv3.5.0 二、镜像生成工具准备 nerdctlv1.7.6buildkitv0.13.2 1 nerdctl安装 下载&#xff1a; wget -c https://github.com/containerd/nerdctl/releases/download/v1.7.6/nerdctl-full-1.7.6-linux-amd64.tar.gz …

【电路笔记】-共基极放大器

共基极放大器 文章目录 共基极放大器1、概述2、等效电路3、电流增益4、输入阻抗5、输出阻抗6、电压增益7、示例:电压、电流和功率增益8、总结1、概述 在本文中,我们将介绍双极晶体管放大器的最后一种拓扑,称为共基极放大器 (CBA)。 下面的图 1 显示了 CBA 的电气图,此处没…

RabbitMQ揭秘:轻量级消息队列的优缺点全解析

我是小米,一个喜欢分享技术的29岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货! 亲爱的读者朋友们,大家好!我是小米,一个热爱技术、喜欢分享的大哥哥。今天我们来聊聊一个在消息队列领域非常重要的工具——RabbitMQ。作为一个在通信…

python简单练习案例-石头剪刀布小游戏

&#x1f308;所属专栏&#xff1a;【python】 ✨作者主页&#xff1a; Mr.Zwq ✔️个人简介&#xff1a;一个正在努力学技术的Python领域创作者&#xff0c;擅长爬虫&#xff0c;逆向&#xff0c;全栈方向&#xff0c;专注基础和实战分享&#xff0c;欢迎咨询&#xff01;…

L53--- 144. 二叉树的后序遍历(深搜)---Java版

1.题目描述 2.思路 &#xff08;1&#xff09;比如 1/ \2 3从根节点开始&#xff1a; 初始时&#xff0c;currentSum 为 0。 根节点的值为 1。 更新后的 currentSum 0 * 10 1 1。 处理左子节点&#xff1a; 当前 currentSum 为 1&#xff08;即路径 “1”&#xff09;。…

AI预测体彩排3采取888=3策略+和值012路或胆码测试6月16日升级新模型预测第1弹

根据前面的预测效果&#xff0c;我对模型进行了重新优化&#xff0c;因为前面的模型效果不是很好。熟悉我的彩友比较清楚&#xff0c;我之前的主要精力是对福彩3D进行各种模型的开发和预测&#xff0c;排三的预测也就是最近1个月才开始搞的。3D的预测&#xff0c;经过对模型的多…

【Emacs Verilog mode保姆级的使用指南】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

FreeBSD jail虚拟容器里装ubuntu系统没有apt命令怎么办?

问题 在FreeBSD jail里使用linux兼容创建了ubuntu环境&#xff0c;但是没有apt命令&#xff0c;该怎么办呢&#xff1f; jail的介绍&#xff1a;FreeBSD jail 容器手册_freebsd虚拟化-CSDN博客 系统是这样进去的&#xff1a; jexec focal chroot /compat/ubuntu /bin/bash …

38、基于卷积神经网络(CNN)的车牌自动识别系统(matlab)

1、原理及流程 1&#xff09;原理 CNN&#xff08;卷积神经网络&#xff09;是一种深度学习模型&#xff0c;可以用于图像识别和分类任务。车牌自动识别系统的原理基本上就是使用CNN模型对车牌图像进行处理和识别。 首先&#xff1a;系统需要收集大量的含有车牌的图像数据作…

异常封装类统一后端响应的数据格式

异常封装类 如何统一后端响应的数据格式 1. 背景 后端作为数据的处理和响应&#xff0c;如何才能和前端配合好&#xff0c;能够高效的完成任务&#xff0c;其中一个比较重要的点就是后端返回的数据格式。 没有统一的响应格式&#xff1a; // 第一种&#xff1a; {"dat…

UniApp+Vue3使用Vant-微信小程序组件

第一步&#xff1a;打开创建好的UniappVue3的项目 第二步&#xff1a;下载Vant-Weapp npm i vant/weapp -S --production 第三步&#xff1a;修改目录名称 wxcomponents 必须是wxcomponents 第四步&#xff1a;将下载好的vant中的dist目录剪切到当前wxcomponents目录下 第五…

贪心算法学习五

例题一 解法&#xff08;贪⼼&#xff09;&#xff1a; 贪⼼策略&#xff1a; 我们的任何选择&#xff0c;应该让这个数尽可能快的变成 1 。 对于偶数&#xff1a;只能执⾏除 2 操作&#xff0c;没有什么分析的&#xff1b; 对于奇数&#xff1a; i. 当 n 1 的时候…

低代码开发MES系统,一周实现数字化

随着工业4.0和智能制造的兴起&#xff0c;企业对于生产过程的数字化、智能化需求日益迫切。制造执行系统&#xff08;MES&#xff09;作为连接计划层与控制层的关键信息系统&#xff0c;在提升生产效率、优化资源配置、保障产品质量等方面发挥着重要作用。然而&#xff0c;传统…

不可不知的Java SE技巧:如何使用for each循环遍历数组

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。运营社区&#xff1a;C站/掘金/腾讯云&#xff1b;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一…

LVGL刷屏优化(基于ESP32)

主要参考资料&#xff1a; 乐鑫ESP-IDF官方手册SPI Flash and External SPI RAM Configuration: https://docs.espressif.com/projects/esp-idf/zh_CN/release-v5.0/esp32s3/api-guides/flash_psram_config.html 目录 驱动和端口优化RAM与PSRAMFLASH SPI与PSRAM SPI LVGL优化修…

使用Vue中的<TransitionGroup/>进入动画不生效不显示问题

Vue中有两个过渡动画组件分别是&#xff1a;<TransitionGroup/> <TransitionGroup/>进入动画不生效不显示问题 &#xff0c;在渲染列表上加上v-if&#xff0c;看代码&#xff0c;让他每次渲染都重新渲染 加上v-if即可 <template> <TransitionGroup nam…

Day01_Ajax入门

文章目录 学习目标一、AJAX 概念和 axios 使用1. 目标2. 讲解2.1 什么是 AJAX ?2.2 什么是服务器&#xff1f;2.3 为何学 AJAX ?2.4 怎么学 AJAX ?2.5 例子2.6 axios语法 二、认识 URL1. 目标2. 讲解2.1 为什么要认识 URL ?2.2 什么是 URL &#xff1f;2.3 URL的组成 &…

手把手教你改造Sentinel Dashboard 实现配置持久化

一. 概述 Sentinel客户端默认情况下接收到 Dashboard 推送的规则配置后&#xff0c;可以实时生效。但是有一个致命缺陷&#xff0c;Dashboard和业务服务并没有持久化这些配置&#xff0c;当业务服务重启后&#xff0c;这些规则配置将全部丢失。 Sentinel 提供两种方式修改规则…