链表(3):双链表

引入

我们之前学的单向链表有什么缺点呢? 

缺点:后一个节点无法看到前一个节点的内容

那我们就多设置一个格子prev用来存放前面一个节点的地址,第一个节点的prev存最后一个节点的地址(一般是null)

这样一个无头双向链表就造好啦😊

老规矩,手搓双链表

初始

和单链表一样,我们也是实现IList接口的方法

初始化差不多,可以去看我前面的博客

数据结构:链表(1)_cx努力编程中的博客-CSDN博客

跟前驱没关系的函数我先放进来

    @Overridepublic boolean contains(int key) {ListNode cur = this.head;while(cur != null){if(cur.val == key){return true;}cur = cur.next;}return false;}@Overridepublic int size() {int count = 0;ListNode cur = this.head;while (cur != null) {count++;cur = cur.next;}return count;}@Overridepublic void display() {ListNode cur = head;while(cur != null){System.out.print(cur.val + " ");cur = cur.next;}System.out.println();}

插入

头插法

实例化一个node,如果只有一个节点的话就把head和last都放在这个节点的下面

node.next = head;

head.prev = node;

head = node;//把head的位置放到node这里

    public void addFirst(int data) {ListNode node = new ListNode(data);if(head == null){head = node;last = node;}else{node.next = this.head;head.prev = node;head = node;}}

尾插法

跟单链表不一样的是,双链表有last,所以时间复杂度是O(1)

    @Overridepublic void addLast(int data) {ListNode node = new ListNode(data);if(head == null){head = node;last = node;}else{last.next = node;node.prev = head;last = node;}}

指定位置插入

比如我们实例化一个节点,想要将其插入到1和2之间

那么我们就要将cur移动到2的位置(走index步)

这个cur的前驱(节点1)的next就是这个新节点的地址

node.next = cur 

cur.prev.next = node(0x123)

node.prev = cur.prev

cur.prev = node

代码:

    @Overridepublic void addIndex(int index, int data) {//检查index是否异常int len = size();if(index < 0 || index > len){System.out.println("异常索引"+index);return;}if(index == 0){//头插法addFirst(data);return;}if(index == len){//尾插法addLast(data);return;}ListNode cur = findIndex(index);ListNode node = new ListNode(data);node.next = cur;cur.prev.next = node;node.prev = cur.prev;cur.prev = node;}

 删除

假如删除中间45这个节点,先让cur走到这个节点,再让45前一个节点的地址等于45后一个节点地址,让45后一个节点的前驱等于45前一个节点的地址

但是假如要删除的是13这个节点(头节点),那么cur.prev.next = cur.next这行代码有问题

所以我们这么干,直接把头节点的后一个节点的前驱prev置为null就行了

                if(cur == head){head = head.next;head.prev = null;

假如要删除的是56这个节点(尾节点),那么cur.next.prev = cur.prev这行代码有问题

那我们这么干,直接把尾节点的前一个节点的next置为null就行了

cur.prev.next = cur.next;

last = last.prev;

我们发现尾节点的删除和中间节点删除有一行代码是一样的

cur.prev.next = cur.next;

我们可以把它作为这二者的公用代码

                    cur.prev.next = cur.next;if(cur.next == null){last = last.prev;}else {cur.next.prev = cur.prev;}

其实这段代码还存在问题

当链表只有一个元素的时候,

 

head = head.next //这行代码一走完表明head此时已经是空的了,下一行代码还说head.prev就根本不存在(注意:head.prev = null是赋值操作,首先你得有head.prev才能进行赋值)

更改代码:

整个remove代码

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

删除指定值的所有相同值的节点

跟上面的代码很像,区别就是删除之后不要return,让cur继续往下走

    @Overridepublic void removeAllKey(int key) {ListNode cur = head;while(cur != null){if(cur.val == key) {if (cur == head) {head = head.next;if (head == null) {last = null;} else {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;}}

清除链表

暴力方法:

head = null;  last = null;

细致方法:

定义一个cur,遍历整个链表,每到一个节点就把prev和next都置为空

    @Overridepublic void clear() {ListNode cur = head;while(cur!=null){ListNode curNext = cur.next;//防止将这个节点的next置为空之后,cur没办法继续遍历cur.prev = null;cur.next = null;cur = curNext;}}

总结:

ArrayList和LinkedList的区别是?

如果是经常根据下标查找的,使用顺序表(ArrayList)或者数组

如果经常进行插入和删除操作的,就使用链表(LinkedList)

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

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

相关文章

VirtualBox Ubuntu扩展虚拟机磁盘空间

关于Orical VM VirtualBox虚拟机安装了ubuntu linux系统&#xff0c;由于需要&#xff0c;磁盘空间不足&#xff0c;需要扩展磁盘空间&#xff0c;最终找到了一个非常简单的方法&#xff0c;上干货。 1、关闭虚拟机 2、运用VBoxManage命令扩展vdi文件的空间 打开windows的命…

CSS 常用样式background背景属性

一、背景颜色 background-color CSS中的background-color是用来设置HTML元素的背景颜色的一个属性。它可以接受各种颜色值&#xff0c;包括具有名称的颜色和十六进制颜色值。 以下是一些示例代码&#xff1a; 设置元素的背景颜色为红色&#xff1a; background-color: red…

Golang 实现接口和继承

小猴子继承了老猴子&#xff0c;这样老猴子拥有的能力包括字段&#xff0c;方法就会自动的被老猴子继承。 小猴子不需要做任何处理就可以拿到老猴子的字段和它的方法&#xff0c;因为是继承关系。 但是小猴子还会其他的技能&#xff0c;比如还会像小鸟一样飞翔&#xff0c;希…

pytorch中的池化函数

PyTorch 提供了多种池化函数&#xff0c;用于对输入数据进行不同类型的池化操作。以下是一些常用的 PyTorch 池化函数&#xff1a; 平均池化&#xff08;Average Pooling&#xff09;: nn.AvgPool1d: 一维平均池化。nn.AvgPool2d: 二维平均池化。nn.AvgPool3d: 三维平均池化。 …

VR全景营销颠覆传统营销,让消费者身临其境

随着VR的普及&#xff0c;各种VR产品、功能开始层出不穷&#xff0c;并且在多个领域都有落地应用&#xff0c;例如文旅、景区、酒店、餐饮、工厂、地产、汽车等&#xff0c;在这个“内容为王”的时代&#xff0c;VR全景展示也是一种新的内容表达方式。 VR全景营销让消费者沉浸式…

postman 获取HTML 里name=token 的值

<input type"hidden" name"token" value"LT-93387-t7KaInf3Fox2Hd0F24eHpBFg7BcNAp" /> 接口返回的HTML&#xff0c;可以使用cheerio获取具体的值&#xff0c;如下&#xff1a; //引入cheerio const $ cheerio.load(responseBody) //解…

计算机毕业设计选什么题目好?springboot 职业技术学院图书管理系统

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

【深度学习实验】卷积神经网络(八):使用深度残差神经网络ResNet完成图片多分类任务

目录 一、实验介绍 二、实验环境 1. 配置虚拟环境 2. 库版本介绍 三、实验内容 0. 导入必要的工具包 1. 构建数据集&#xff08;CIFAR10Dataset&#xff09; a. read_csv_labels&#xff08;&#xff09; b. CIFAR10Dataset 2. 构建模型&#xff08;FeedForward&#x…

SQL开发笔记之专栏介绍

Sql是用于访问和处理数据库的标准计算机语言&#xff0c;使用SQL访问和处理数据系统中的数据&#xff0c;这类数据库包括&#xff1a;Mysql、PostgresSql、Oracle、Sybase、DB2等等&#xff0c;数据库无非围绕着“增删改查”的核心业务进行开发。并且目前绝大多数的后端程序开发…

构建精致 Chrome 插件:开箱即用的 TypeScript 模板 | 开源日报 No.51

tonsky/FiraCode Stars: 72.7k License: OFL-1.1 Fira Code 是一种免费的等宽字体&#xff0c;具有编程连字符。 Fira Code 提供了丰富多样的箭头和标点符号调整功能。Fira Code 支持各种不同的字符变体、风格集和其他字体特性&#xff0c;以满足用户个性化需求。Fira Code …

【Hello Algorithm】暴力递归到动态规划(一)

暴力递归到动态规划&#xff08;一&#xff09; 斐波那契数列的动态规划机器人走路初级递归初级动态规划动态规划 先后选牌问题初级递归初级动态规划动态规划 我们可以一句话总结下动态规划 动态规划本质是一种以空间换时间的行为 如果你发现有重复调用的过程 在经过一次之后把…

windows频繁更新问题解决方案

解决方案&#xff1a;将更新策略增加到无穷大 1.windowsr 输入regedit 2.找到&#xff1a;HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings 3.右键新建DWORD32 4.命名&#xff1a;FlightSettingsMaxPauseDays 5.双击&#xff1a;数值数据改为4321 基数&#…

Spring是什么?为什么要使用Spring?

目录 前言 一、Spring是什么&#xff1f; 1.1 轻量级 1.2 JavaEE的解决方案 二、为什么要使用Spring 2.1 传统方式完成业务逻辑 2.2 使用Spring模式完成业务逻辑 三、为什么使用Spring&#xff1f; 前言 本文主要介绍Spring是什么&#xff0c;并且解释为何要去使用Spring&…

vite + vu3 + ts 项目,npm run build 报错

新建了vite 项目&#xff0c;build的时候报错&#xff1a; npm ERR! demo10.0.0 build: vue-tsc && vite build npm ERR! Exit status 1 npm ERR! npm ERR! Failed at the demo10.0.0 build script.npm ERR! This is probably not a problem with npm. There is like…

【Vue Router 3】入门

简介 Vue Router让SPA&#xff08;Single-page Application&#xff09;的构建更加容易。 Vue Router的功能&#xff1a; 嵌套的路由/视图映射模块化的、基于组件的router配置route params, query, wildcards由Vue过渡系统支持的视图过渡效果细粒度&#xff08;fine-grained…

c语言练习87:合并两个有序数组

合并两个有序数组 合并两个有序数组https://leetcode.cn/problems/merge-sorted-array/ 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2&#xff0c;另有两个整数 m 和 n &#xff0c;分别表示 nums1 和 nums2 中的元素数目。 请你 合并 nums2 到 nums1 中&#xff…

动态资源平衡:主流虚拟化 DRS 机制分析与 SmartX 超融合的实现优化

资源的动态调度是虚拟化软件&#xff08;或超融合软件&#xff09;中的一项重要功能&#xff0c;主要指在虚拟化集群中&#xff0c;通过动态改变虚拟机的分布&#xff0c;达到优化集群可用性的目标。这一功能以 VMware vSphere 发布的 Distributed Resource Scheduler&#xff…

day62:ARMday9,I2c总线通信

作业&#xff1a;按键中断实现LED1、蜂鸣器、风扇 key_in.c: #include "key_in.h"void gpio_init() {//RCC使能//GPIOERCC->MP_AHB4ENSETR | (0x1<<4);//GPIOBRCC->MP_AHB4ENSETR | (0x1<<1);//PE10、PB6、PE9输出模式GPIOE->MODER & ~(0…

AutoGPT:让 AI 帮你完成任务事情 | 开源日报 No.54

Significant-Gravitas/AutoGPT Stars: 150.4k License: MIT AutoGPT 是开源 AI 代理生态系统的核心工具包。它采用模块化和可扩展的框架&#xff0c;使您能够专注于以下方面&#xff1a; 构建 - 为惊人之作打下基础。测试 - 将您的代理调整到完美状态。查看 - 观察进展成果呈…

基于SpringBoot的网上订餐系统

基于SpringBoot的网上订餐系统的设计与实现 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBootMyBatisVue工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 【主要功能】 角色&#xff1a;用户、管理员管理员&#xff1a;登录、个人中心、会员管理、…