java双向链表解析实现双向链表的创建含代码

双向链表

  • 一.双向链表
  • 二.创建MyListCode类实现双向链表创建
    • 一.AddFirst创建(头插法)
    • 二.AddLast创建(尾叉法)
    • 三.size
    • 四.remove(指定任意节点的首位删除)
    • 五.removeAll(包含任意属性值的所有删除)
    • 六.AddIndex(给任意位置添加一个节点)
    • 七.contains(无)
    • 八.partition(区分链表的大小范围)
    • 九.display(打印)
  • 接口类
  • MyListNode整体代码
  • Test测试类代码

一.双向链表

单向链表从头部开始我们的每一个节点指向后驱的节点。
此处为单向链表

单向链表

双向链表是相互指向前驱以及后驱的链表
前驱链表我们需要在我们的MyListCode内部类中在定义一个previous来接收每一个前驱的地址

在这里插入图片描述想要删除任意节点可以直接通过访问下一个节点使其prev获取想要删除的上一个节点,然后将想要删除的上一个节点.next获取到被删除对象下一个节点的指向
在这里插入图片描述
这里我们可以模拟实现MyListCode类中的一些方法,入头插法、尾叉法、任意位置插入节点、指定元素删除含有该元素的第一个节点、指定元素删除含有该元素的所有节点等…

二.创建MyListCode类实现双向链表创建

public class MyListNode implements IList {static class Node{public int val;//获取的后一个节点public Node next;//获取的前一个节点public Node prev;public Node(int val) {this.val = val;}}//始终在第一个节点public Node head;//指向最后一个节点public Node last;}

一.AddFirst创建(头插法)

这里当头部为null,没有头部和尾巴,我们将新节点作为头和尾,如果不为null,将每次产生的新节点对象放到头部,头部的pre与新节点相连,头部更新最新节点

  @Overridepublic void addFirst(int data) {Node node=new Node(data);if(this.head==null){//head指向头部,last指向尾巴this.head=node;this.last=node;}else{//不为空将新节点插入头部并将头部的pre置为新节点,最后更新头部位置node.next=this.head;this.head.prev=node;this.head=node;}}

二.AddLast创建(尾叉法)

这里考虑的是当head为空时,我们的头和尾巴都将获取新的节点,如果不为空,我们只需要移动last,将last的下一个节点获取到新的节点,新的节点pre指向last,最后last走向新节点,得到尾巴

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

三.size

从头部开始遍历或者尾部开始遍历

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

四.remove(指定任意节点的首位删除)

首先判断如果头部值为空,说明没有节点,头部的下一个节点如果为key值则直接返回key(因为这里只是删除一个,所以不考虑多个带key的节点),然后遍历如果最后一个节点为key,它的下一个节点为null,则将双向节点置为null,如果不为null,就删除这个节点

  @Overridepublic void remove(int key) {if (this.head == null) {return;}if(this.head.val==key){//头节点为key将其更换为后驱节点,将后驱节点的prev置空this.head=this.head.next;this.head.prev=null;return;}Node cur=this.head.next;while(cur!=null){if(cur.val==key){//最后一个节点为key将前驱的下一项置空并将cur的pre置空if(cur.next==null){cur.prev.next=null;cur.prev=null;return;}else{//不是最后一个节点将前驱节的下一节点为当前节点下一项//当前节点的下一项的前驱为当前项的前驱cur.prev.next=cur.next;cur.next.prev=cur.prev;return;}}cur=cur.next;}}

五.removeAll(包含任意属性值的所有删除)

首先判断是否头部为空
判断最后一个last值是否时key,是key将双节点置空
然后判断key值,将key值在节点中删除
最后判断头节点是否为key,并将头节点置空

@Overridepublic void removeAll(int key) {if(this.head==null){return;}if(this.last.val==key) {//如果最后一项的值为key,将last前一项保留下来,最后赋值给last使其尾部更新Node pre=this.last.prev;this.last.prev.next = null;this.last.prev = null;this.last=pre;}Node cur=this.head.next;while(cur!=null){//cur的值如果为key清理该节点指向if(cur.val==key){cur.prev.next=cur.next;cur.next.prev=cur.prev;}cur=cur.next;}//最后判断head的值是否是keyif(this.head.val==key){this.head=this.head.next;}//如果head有数据将head头的前节点置空if(this.head!=null){this.head.prev=null;}}

六.AddIndex(给任意位置添加一个节点)

首先判断头部是否为空
判断该坐标是否合法,如果该坐标在0或者在尾巴,则头插法和尾叉法
将给的坐标作为循环条件节点开始走,跳出循环后改节点位置就是要添加的位置
首先要把改节点的坐标向后移动一位,插入其中间
单链表的话将cur先指向后一个节点在指向前一个节点

 @Overridepublic void addIndex(int index,int data)throws RuntimeException {if(this.head==null){return;}try {if(index<0||index>size()){throw new RuntimeException("错误范围"+size());}}catch (RuntimeException e){e.printStackTrace();}if(index==0){addFirst(data);return;}if(index==size()){addLast(data);return;}Node node=new Node(data);Node cur=this.head;while(index>0){//出来后就是要插入的范围cur=cur.next;index--;}//在任意位置新增一个节点node.next=cur;node.prev=cur.prev;cur.prev=node;node.prev.next=node;return ;}

七.contains(无)

 @Overridepublic boolean contains(int key) {if(this.head==null){return false;}Node cur=this.head;while(cur!=null){if(cur.val==key){return true;}cur=cur.next;}return false;}

八.partition(区分链表的大小范围)

    @Overridepublic Node partition(Node node,int x) {if (node == null) {return null;}Node cur = node;Node min=null;Node minEnd=null;Node max=null;Node maxEnd=null;while (cur != null) {if(cur.val<x){if(min==null){min=cur;minEnd=cur;}else{minEnd.next=cur;minEnd=minEnd.next;}}else{if(max==null){max=cur;maxEnd=cur;}else{maxEnd.next=cur;maxEnd=maxEnd.next;}}cur = cur.next;}if(min==null){return max;}if(maxEnd!=null){maxEnd.next=null;}minEnd.next=max;return min;}
}

九.display(打印)

@Overridepublic void display() {Node cur=this.head;while(cur!=null){System.out.print(cur.val+" ");cur=cur.next;}System.out.println();}

接口类

public interface IList {public void display();public int size();public void addFirst(int data);//新增一个节点放到头部public void addLast(int data);//新增一个节点放到尾部public void remove(int key);//删除第一个val值为key的节点public void removeAll(int key);//删除所有val值的节点public void addIndex(int index,int data);//在任意一个位置放入一个节点public boolean contains(int key);//是否包含key数值这个节点public MyListNode.Node partition(MyListNode.Node node,int x);//指定一个值,将数值小的放在前,将数值大的放在后
}

MyListNode整体代码

import java.util.List;public class MyListNode implements IList {static class Node{public int val;public Node next;public Node prev;public Node(int val) {this.val = val;}}//始终在第一个节点public Node head;//指向最后一个节点public Node last;@Overridepublic void addFirst(int data) {Node node=new Node(data);if(this.head==null){this.head=node;this.last=node;}else{node.next=this.head;this.head.prev=node;this.head=node;}}@Overridepublic void addLast(int data) {Node node=new Node(data);if(this.head==null){this.head=node;this.last=node;}else {this.last.next = node;node.prev = last;last=node;}}@Overridepublic int size() {if(this.head==null){return 0;}Node cur=this.head;int count=0;while(cur!=null){count++;cur=cur.next;}return count;}public int size2(){if(this.head==null){return 0;}Node end=this.last;int count=0;while(end!=null){count++;end=end.prev;}return count;}@Overridepublic void display() {Node cur=this.head;while(cur!=null){System.out.print(cur.val+" ");cur=cur.next;}System.out.println();}public void display2(){Node cur=this.last;while(cur!=null){System.out.print(cur.val+" ");cur=cur.prev;}System.out.println();}@Overridepublic void remove(int key) {if (this.head == null) {return;}if(this.head.val==key){//头节点为key将其更换为后驱节点,将后驱节点的prev置空this.head=this.head.next;this.head.prev=null;return;}Node cur=this.head.next;while(cur!=null){if(cur.val==key){//最后一个节点为key将前驱的下一项置空并将cur的pre置空if(cur.next==null){cur.prev.next=null;cur.prev=null;return;}else{//不是最后一个节点将前驱节的下一节点为当前节点下一项//当前节点的下一项的前驱为当前项的前驱cur.prev.next=cur.next;cur.next.prev=cur.prev;return;}}cur=cur.next;}}@Overridepublic void removeAll(int key) {if(this.head==null){return;}if(this.last.val==key) {//如果最后一项的值为key,将last前一项保留下来,最后赋值给last使其尾部更新Node pre=this.last.prev;this.last.prev.next = null;this.last.prev = null;this.last=pre;}Node cur=this.head.next;while(cur!=null){//cur的值如果为key清理该节点指向if(cur.val==key){cur.prev.next=cur.next;cur.next.prev=cur.prev;}cur=cur.next;}//最后判断head的值是否是keyif(this.head.val==key){this.head=this.head.next;}//如果head有数据将head头的前节点置空if(this.head!=null){this.head.prev=null;}}@Overridepublic void addIndex(int index,int data)throws RuntimeException {if(this.head==null){return;}if(index==0){addFirst(data);return;}if(index==size()){addLast(data);return;}try {if(index<0||index>size()){throw new RuntimeException("错误范围"+size());}}catch (RuntimeException e){e.printStackTrace();}Node node=new Node(data);Node cur=this.head;while(index>0){//出来后就是要插入的范围cur=cur.next;index--;}//在任意位置新增一个节点node.next=cur;node.prev=cur.prev;cur.prev=node;node.prev.next=node;return ;}@Overridepublic boolean contains(int key) {if(this.head==null){return false;}Node cur=this.head;while(cur!=null){if(cur.val==key){return true;}cur=cur.next;}return false;}@Overridepublic Node partition(Node node,int x) {if (node == null) {return null;}Node cur = node;Node min=null;Node minEnd=null;Node max=null;Node maxEnd=null;while (cur != null) {if(cur.val<x){if(min==null){min=cur;minEnd=cur;}else{minEnd.next=cur;minEnd=minEnd.next;}}else{if(max==null){max=cur;maxEnd=cur;}else{maxEnd.next=cur;maxEnd=maxEnd.next;}}cur = cur.next;}if(min==null){return max;}if(maxEnd!=null){maxEnd.next=null;}minEnd.next=max;return min;}
}

Test测试类代码

public class Test {public static void main(String[] args) {MyListNode myListNode=new MyListNode();myListNode.addLast(3);myListNode.addLast(5);myListNode.addLast(7);myListNode.removeAll(6);
//        System.out.println(myListNode.last.val);
//        myListNode.display();myListNode.addIndex(1,9);System.out.println(myListNode.contains(3));myListNode.display();int len1 =  myListNode.size();int len2 =  myListNode.size();System.out.println(len1+"size");System.out.println(len2+"size1");MyListNode myListNode1=new MyListNode();myListNode1.addLast(3);myListNode1.addLast(3);myListNode1.addLast(8);myListNode1.addLast(9);myListNode1.addLast(19);myListNode1.addLast(3);myListNode1.display();myListNode1.display2();myListNode1.partition(myListNode1.head,5);myListNode1.display();myListNode1.display2();}
}

写的也有很多不好的地方,希望大佬们多多指点,谢谢!!祝大家开心快乐

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

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

相关文章

VMWare虚拟机NAT模式下与外部主机(非宿主机)通信

VMWare虚拟机NAT模式下与外部主机(非宿主机)通信 1. VMWare虚拟机网络 VMWare的三种网络工作模式&#xff1a; Bridged&#xff1a;桥接模式NAT&#xff1a;网络地址转换模式Host-Only &#xff1a;仅主机模式 VMWare 网络连接配置界面如下&#xff1a; 在本次测试环境中&a…

Mac保护电池健康,延长电池使用寿命的好方法

使用Mac的过程中&#xff0c;如何延长电池的使用寿命是大家非常关心的问题&#xff0c;而养成一个良好的充电习惯能够有效的延长电池的使用寿命 避免过度充电和过度放电能够有效的保护电池&#xff0c;因此长时间的充电与长时间放点都不可取&#xff0c;但是在日常的使用过程中…

显示器接口种类 | 附图片

显示器接口类型主要包括VGA、DVI、HDMI、DP和USB Type-C等。 VGA、DVI、HDMI、DP和USB Type-C 1. 观察 VGA接口:15针 DP接口&#xff1a;在DP接口旁&#xff0c;都有一个“D”型的标志。 电脑主机&#xff1a;DP(D) 显示器&#xff1a;VGA(15针) Ref https://cloud.tenc…

qt QUndoCommand 与 QUndoStack详解

1、概述 QUndoCommand 和 QUndoStack 是 Qt 框架中用于实现撤销/重做&#xff08;undo/redo&#xff09;功能的两个核心类。QUndoCommand 是表示单个可撤销操作的基类&#xff0c;而 QUndoStack 则负责管理这些命令的堆栈&#xff0c;提供撤销和重做操作的接口。 QUndoCommand…

双指针(二)双指针到底是怎么个事

一.有效的三角形个数 有效的三角形个数 class Solution {public int triangleNumber(int[] nums) {Arrays.sort(nums);int i0,end nums.length-1;int count 0;for( i end;i>2;i--){int left 0;int right i-1;while(left<right){if(nums[left]nums[right]>nums…

springboot的增删改查商城小实践(b to c)

首先准备一张表&#xff0c;根据业务去设计表 订单编号是参与业务的&#xff0c;他那订单编号里面是有特殊意义的&#xff0c;比如说像什么一些年月日什么的&#xff0c;一些用户的ID都在那编号里面呢&#xff1f;不能拿这种东西当主件啊 根据数据量去决定数据类型 价格需要注意…

动态规划-背包问题——416.分割等和子集

1.题目解析 题目来源 416.分割等和子集——力扣 测试用例 2.算法原理 1.状态表示 这里背包问题基本上和母题的思路大相径庭&#xff0c;母题请见 [模板]01.背包 &#xff0c;这里的状态表示与装满背包的情况类似&#xff0c;第二个下标就是当选择的物品体积直接等于j时是否可…

开源 - Ideal库 -获取特殊时间扩展方法(四)

书接上回&#xff0c;我们继续来分享一些关于特殊时间获取的常用扩展方法。 01、获取当前日期所在月的第一个指定星期几 该方法和前面介绍的获取当前日期所在周的第一天&#xff08;周一&#xff09;核心思想是一样的&#xff0c;只是把求周一改成求周几而已&#xff0c;当然其…

移位寄存器设计—FDRE、SRL16E及原语约束

信号处理中&#xff0c;实现数据对齐时&#xff0c;常常对单bit或多bit信号进行打拍操作&#xff0c;这个可以通过移位寄存器实现&#xff0c;SLICEM中的SRL即为移位寄存器。 这里主要记录下不同写法的效果。 1 //同步复位2 module static_multi_bit_sreg_poor #(3 parame…

AFK架构设计思想概述

一、AKF的核心思想 AKF架构设计的核心思想源于对系统可扩展性、可用性和灵活性的深刻理解。AKF&#xff08;Availability, Scalability, Flexibility&#xff09;架构模型由Martin L. Abbott和Michael T. Fisher在《The Art of Scalability》一书中提出&#xff0c;旨在帮助工…

【layui】echart的简单使用

图表类型切换&#xff08;柱形图和折线图相互切换&#xff09; <title>会员数据</title><div class"layui-card layadmin-header"><div class"layui-breadcrumb" lay-filter"breadcrumb"><a lay-href""&g…

期权开户难不难?期权开户成功后当天是否能交易

期权开户难不难&#xff1f;这取决于投资者的准备情况和所选的开户途径。对于满足一定资金和经验要求的投资者来说&#xff0c;通过正规期货公司或期权交易平台进行开户&#xff0c;虽然流程相对复杂&#xff0c;但只要遵循步骤&#xff0c;仍然可以顺利完成&#xff0c;下文为…

Java并发无锁篇--乐观锁(非阻塞)

共享模型之无锁 问题提出 package com.zjy.unlock;import java.util.ArrayList; import java.util.List;public class AccountDemo {public static void main(String[] args) {Account account new AccountUnsafe(10000);Account.demo(account);} }class AccountUnsafe impl…

分享三个python爬虫案例

一、爬取豆瓣电影排行榜Top250存储到Excel文件 近年来&#xff0c;Python在数据爬取和处理方面的应用越来越广泛。本文将介绍一个基于Python的爬虫程序&#xff0c;用于抓取豆瓣电影Top250的相关信息&#xff0c;并将其保存为Excel文件。 获取网页数据的函数&#xff0c;包括以…

第8章利用CSS制作导航菜单

8.1 水平顶部导航栏 <!DOCTYPE html> <html><head><meta charset"utf-8" /><title></title></head><body><center><h3>简单水平菜单导航栏</h3></center><hr /><nav><ul&g…

Spring Plugin与策略模式:打造动态可扩展的应用

目录 一、策略模式 二、Spring Plugin 2.1 Spring Plugin 实现策略模式开发 2.2 策略模式优缺点 三、Spring Plugin 原理 一、策略模式 策略模式是一种设计模式&#xff0c;它允许程序在运行中动态的选择不同的行为方式进行动态执行。策略模式的核心思想是将行为封装在一个个…

spark的学习-05

SparkSql 结构化数据与非结构化数据 结构化数据就类似于excel表中的数据&#xff08;统计的都是结构化的数据&#xff09;一般都使用sparkSql处理结构化的数据 结构化的文件&#xff1a;JSON、CSV【以逗号分隔】、TSV【以制表符分隔】、parquet、orc 结构化的表&#xff1a;…

Android 源码的下载与编译

Android 源码的下载与编译 本章节主要介绍安卓系统的编译以及编译产物&#xff0c;根据我自己的经验只总结个人觉得重要的部分。 有价值的博客&#xff1a; https://blog.csdn.net/wuye110/article/details/8463409 https://juejin.cn/post/7288166472131018786 值得一看的…

基于Python的药房管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

Golang | Leetcode Golang题解之第542题01矩阵

题目&#xff1a; 题解&#xff1a; type point struct{x, y int }var dirs []point{{-1, 0}, {1, 0}, {0, -1}, {0, 1}}func updateMatrix(mat [][]int) [][]int {var m, n len(mat), len(mat[0])var res make([][]int, m)var visited make([][]bool, m)var queue []poin…