Java_简单实现无头单向非循环链表_简单实现LinkedList

文章目录

  • 一、ArrayList的优缺点
  • 二、链表
    • 1.链表的概念及结构
    • 2.链表的分类
      • 1、单向或者双向
      • 2、带头或者不带头
      • 3、循环或者非循环
  • 三、实现无头单向非循环链表
    • 1.定义接口
    • 2.定义MySingleList
    • 3.成员
      • 1、节点类(定义在MySingList类里)
      • 2、头节点引用
    • 4.打印链表实现dispaly(这是方便测试写的)
    • 5.得到单链表的长度 size
    • 6.查找是否包含关键字key是否在单链表当中 contions
    • 7.头插法 addFirst
    • 8.尾插法 addLast
    • 9、任意位置插入,第一个数据节点为0号下标 addIndex
    • 10、删除第一次出现关键字为key的节点 remove
    • 11.删除所有值为key的节点 removeAllKey
    • 12.删除所有值为key的节点 clear
  • 四、练习
    • 1.移除链表元素
    • 2.反转链表
    • 3.链表的中间节点
    • 4.链表中倒数第k个节点
    • 5.合并两个有序链表
    • 6.链表分割
    • 7.链表回文结构
    • 8.相交链表
    • 9.环形链表
    • 10.环形链表2
  • 五、 模拟实现LinkedList
    • 1.定义接口
    • 2.定义MyLinkedList
    • 3.成员
      • 1、节点类
      • 2、头引用和尾引用
    • 4.打印链表 display
    • 5.查找是否包含关键字key是否在单链表当中 contions
    • 6.头插法 addFirst
    • 7.尾插法 addLast
    • 8.任意位置插入,第一个数据节点为0号下标 addIndex
    • 9.得到单链表的长度 size
    • 10.删除第一次出现关键字为key的节点 remove
    • 11.删除所有值为key的节点 removeAllKey
    • 12.清空 clear
  • 六、LinkedList
    • 1.遍历
    • 2.ArrayList和LinkedList的区别?


一、ArrayList的优缺点

缺点:
1.插入数据必须移动其他数据,最坏情况下,就是插入到0位置。时间复杂度O(N)
2.删除数据也需要移动数据,最坏情况下,就是删除0位置。时间复杂度O(N)
3.扩容之后,有可能会浪费空间
优点:
1.在给定下标进行查找的时候,时间复杂度O(1)
总结:顺序表比较适合进行给定下标查找的场景

二、链表

1.链表的概念及结构

链表是一种物理存储结构上非连续存储结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的 。就像火车一样是一节一节的。
在这里插入图片描述
火车之间用挂钩相连,每个节点都存储下一个节点的物理地址。

在这里插入图片描述

2.链表的分类

1、单向或者双向

在这里插入图片描述

2、带头或者不带头

在这里插入图片描述

3、循环或者非循环

在这里插入图片描述
无头双向链表:在Java的集合框架库中LinkedList底层实现就是无头双向循环链表

三、实现无头单向非循环链表

1.定义接口

public interface IList {//头插法public void addFirst(int data);//尾插法public void addLast(int data);//任意位置插入,第一个数据节点为0号下标public void addIndex(int index,int data);//查找是否包含关键字key是否在单链表当中public boolean contains(int key);//删除第一次出现关键字为key的节点public void remove(int key);//删除所有值为key的节点public void removeAllKey(int key);//得到单链表的长度public int size();public void clear();public void display();
}

2.定义MySingleList

public class MySingleList implements IList{@Overridepublic void addFirst(int data) {}@Overridepublic void addLast(int data) {}@Overridepublic void addIndex(int index, int data) {}@Overridepublic boolean contains(int key) {return false;}@Overridepublic void remove(int key) {}@Overridepublic void removeAllKey(int key) {}@Overridepublic int size() {return 0;}@Overridepublic void clear() {}@Overridepublic void display() {}
}

3.成员

1、节点类(定义在MySingList类里)

节点类包含存储数据和下一个节点引用。

   static class ListNode{public int val;public ListNode next;public ListNode(int val){this.val = val;}}

2、头节点引用

 public ListNode head;

4.打印链表实现dispaly(这是方便测试写的)

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

5.得到单链表的长度 size

    @Overridepublic int size() {ListNode cur= head;int ret = 0;while(cur!=null){ret++;cur = cur.next;}return ret;}

6.查找是否包含关键字key是否在单链表当中 contions

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

7.头插法 addFirst

    @Overridepublic void addFirst(int data) {ListNode newhead = new ListNode(data);newhead.next = head;head = newhead;}

8.尾插法 addLast

    @Overridepublic void addLast(int data) {ListNode node= new ListNode(data);if(head==null){head = node;}else {//找尾ListNode cur = head;while(cur.next!=null){cur = cur.next;}cur.next = node;}}

9、任意位置插入,第一个数据节点为0号下标 addIndex

    private  ListNode searchPrev(int index){ListNode cur = head;int count = index-1;while(count--!=0){cur = cur.next;}return cur;}@Overridepublic void addIndex(int index, int data) {if(index<0||index>size()){return;}ListNode temp = new ListNode(data);if(index==0){temp.next= head;head=temp;}else{ListNode cur= searchPrev(index);temp.next = cur.next;cur.next =temp;}}

10、删除第一次出现关键字为key的节点 remove

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

11.删除所有值为key的节点 removeAllKey

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

12.删除所有值为key的节点 clear

    public void clear() {while(head!=null){head.val = 0;//如果用泛型就是nullhead.next = null;head = head.next;}}

四、练习

1.移除链表元素

移除链表元素
我这里创了一个头节点headnode,这样后面包括head都可以用一样处理方式,最后返回头节点的下一个节点。

class Solution {public ListNode removeElements(ListNode head, int val) {ListNode headnode = new ListNode();headnode.next = head;ListNode cur = headnode;while(cur.next!=null){if(cur.next.val==val){cur.next = cur.next.next;}else {cur= cur.next;}}return headnode.next;}
}

2.反转链表

反转链表

class Solution {public ListNode reverseList(ListNode head) {ListNode pre = null;ListNode cur = head;while (cur!=null){ListNode temp = cur.next;cur.next =pre;pre =cur;pre = cur;cur =temp;}return pre;}
}

3.链表的中间节点

快慢指针:快的一步跳俩节点,慢的跳一节点,当快的到尾,慢的就到了中间。

class Solution {public ListNode middleNode(ListNode head) {ListNode fast = head;ListNode low = head;while(fast!=null){if(fast.next!=null){fast = fast.next;low = low.next;}fast = fast.next;}return low;}
}

4.链表中倒数第k个节点

链表中倒数第k个节点

import java.util.*;
/*
public class ListNode {int val;ListNode next = null;ListNode(int val) {this.val = val;}
}*/
public class Solution {public ListNode FindKthToTail(ListNode head,int k) {ListNode cur = head;int count = 0;while(cur!=null){count++;cur= cur.next;}ListNode ret = head;count=count-k;if(count<0){return null;}while(count--!=0){ret = ret.next;}return ret;}
}

5.合并两个有序链表

合并两个有序链表

class Solution {public ListNode mergeTwoLists(ListNode list1, ListNode list2) {ListNode cur1 = list1;ListNode cur2 = list2;ListNode head = new ListNode();ListNode end = head;while(cur1!=null&&cur2!=null){if(cur1.val>cur2.val){end.next = cur2;cur2 = cur2.next;}else{end.next = cur1;cur1 =cur1.next;}end = end.next;        }if(cur1==null){end.next = cur2;}else if(cur2==null){end.next = cur1;}return head.next;}
}

6.链表分割

链表分割
注意要把大于k的节点最后一个的next置为null可能会出现环

public class Partition {public ListNode partition(ListNode pHead, int x) {ListNode smallHead = new ListNode(0);ListNode bigHead = new ListNode(0);ListNode smallCur = smallHead;ListNode bigCur = bigHead;ListNode cur = pHead;while(cur!=null){if(cur.val<x){smallCur.next = cur;smallCur =smallCur.next;}else{bigCur.next =cur;bigCur = bigCur.next;}cur = cur.next;}bigCur.next = null;smallCur.next = bigHead.next;return smallHead.next;}
}

7.链表回文结构

链表回文结构
1、用快慢指针找到中间节点
2、反转后面节点
3、从两边向中间验证是否是回文

import java.util.*;/*
public class ListNode {int val;ListNode next = null;ListNode(int val) {this.val = val;}
}*/
public class PalindromeList {public boolean chkPalindrome(ListNode A) {ListNode fast = A;ListNode slow = A;while(fast!=null&&fast.next!=null){fast= fast.next.next;slow =slow.next;}ListNode pre = slow;slow = slow.next;while(slow!=null){ListNode temp = slow.next;slow.next = pre;pre = slow;slow = temp;}slow =A;while(slow!=pre){if(slow.val!=pre.val){return false;}if(slow.next==pre){break;}slow = slow.next;pre = pre.next;}return true;}
}

8.相交链表

相交链表
1、先测出两链表的长度
2、遍历俩链表,让较长的先走相差长度的步数
3、比较节点

/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode(int x) {*         val = x;*         next = null;*     }* }*/
public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {ListNode curA = headA;ListNode curB = headB;int countA=0,countB=0;while(curA!=null){countA++;curA =curA.next;}while(curB!=null){countB++;curB =curB.next;}curA = headA;curB = headB;if(countA>countB){int differ = countA-countB;while(differ--!=0){curA = curA.next;}}else{int differ = countB-countA;while(differ--!=0){curB = curB.next;}}while(curA!=null){if(curA==curB){return curA;}curA = curA.next;curB = curB.next;}return null;}
}

9.环形链表

环形链表
快慢指针,相遇即为环形

/*** Definition for singly-linked list.* class ListNode {*     int val;*     ListNode next;*     ListNode(int x) {*         val = x;*         next = null;*     }* }*/
public class Solution {public boolean hasCycle(ListNode head) {if(head==null){return false;}ListNode fast = head;ListNode slow = head;while(fast!=null&&fast.next!=null){fast = fast.next.next;slow =slow.next;if(fast==slow){return true;}}return false;}
}

10.环形链表2

环形链表2
在快慢相遇时,在开头在创建指针,和相遇慢指针一起走,再次相遇即为环形节点。
在这里插入图片描述

public class Solution {public ListNode detectCycle(ListNode head) {ListNode fast = head;ListNode slow =head;while(fast!=null&&fast.next!=null){fast = fast.next.next;slow = slow.next;if(fast==slow){break;}}if(fast==null||fast.next==null){return null;}ListNode cur = head;while(cur!=slow){cur = cur.next;slow = slow.next;}return cur;}
}

五、 模拟实现LinkedList

LinkedList是无头双向链表

1.定义接口

//头插法
public void addFirst(int data){ }
//尾插法
public void addLast(int data){}
//任意位置插入,第一个数据节点为0号下标
public void addIndex(int index,int data){}
//查找是否包含关键字key是否在单链表当中
public boolean contains(int key){}
//删除第一次出现关键字为key的节点
public void remove(int key){}
//删除所有值为key的节点
public void removeAllKey(int key){}
//得到单链表的长度
public int size(){}
public void display(){}
public void clear(){}

2.定义MyLinkedList

public class MyLinkedList implements IList{@Overridepublic void addFirst(int data) {}@Overridepublic void addLast(int data) {}@Overridepublic void addIndex(int index, int data) {}@Overridepublic boolean contains(int key) {return false;}@Overridepublic void remove(int key) {}@Overridepublic void removeAllKey(int key) {}@Overridepublic int size() {return 0;}@Overridepublic void display() {}@Overridepublic void clear() {}
}

3.成员

1、节点类

存储数据,指向前一个节点的引用,指向后一个节点的引用。

    class ListNode {public int val;public  ListNode prev;public ListNode next;public ListNode(int val){this.val = val;}}

2、头引用和尾引用

    public ListNode head;public ListNode last;

4.打印链表 display

    public void display() {ListNode cur = head;while(cur!=null){System.out.print(cur.val+" ");cur = cur.next;}System.out.println();}

5.查找是否包含关键字key是否在单链表当中 contions

    public boolean contains(int key) {ListNode cur = head;while(cur!=null){if(cur.val==key){return true;}cur = cur.next;}return false;}

6.头插法 addFirst

    public void addFirst(int data) {ListNode node = new ListNode(data);node.next = head;node.prev = node;head = node;}

7.尾插法 addLast

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

8.任意位置插入,第一个数据节点为0号下标 addIndex

    public void addIndex(int index, int data) {if(index<0||index>size()){System.out.println("不合法index");return;}if(index==0){addFirst(data);return;}if(index==size()){addLast(data);return;}int count = index-1;ListNode cur = head;while(count--!=0){cur = cur.next;}ListNode node =new ListNode(data);node.prev = cur;node.next = cur.next;cur.next.prev =  node;cur.next = node;}

9.得到单链表的长度 size

   public int size() {ListNode cur =head;int count =0;while(cur!=null){count++;cur =cur.next;}return count;}

10.删除第一次出现关键字为key的节点 remove

注意以下特殊情况:
1、删除头一个情况
2、删除头一个情况且只有一个节点
3、删除最后一个

   public 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;}cur =cur.next;}}

11.删除所有值为key的节点 removeAllKey

同上但删除不return

    public 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;}}

12.清空 clear

    public void clear() {ListNode cur = head;while(cur!=null){cur.prev = null;cur.val =-1;//如果是引用要置空nullListNode temp = cur.next;cur.next = null;cur = temp;}head =null;last =null;}

六、LinkedList

1.遍历

    public static void main(String[] args) {LinkedList<Integer> list = new LinkedList<>();list.add(1);list.add(2);list.add(3);list.add(4);System.out.println(list);System.out.println();System.out.println("========");for(Integer x:list){System.out.print(x+" ");}System.out.println();System.out.println("========");for(int i = 0;i<list.size();i++){System.out.print(list.get(i)+" ");}System.out.println();System.out.println("========");ListIterator<Integer> it = list.listIterator();while(it.hasNext()){System.out.print(it.next()+" ");}System.out.println();ListIterator<Integer> it2 = list.listIterator(list.size());while(it2.hasPrevious()){System.out.print(it2.previous()+" ");}System.out.println();}

在这里插入图片描述

2.ArrayList和LinkedList的区别?

在这里插入图片描述

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

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

相关文章

Docker 容器卷

1、概念介绍 如果是CentOS7安全模块会比之前系统版本加强&#xff0c;不安全的会先禁止&#xff0c;所以目录挂载的情况被默认为不安全的行为&#xff0c;在SELinux里面挂载目录被禁止掉了&#xff0c;如果要开启&#xff0c;我们一般使用--privlegedtrue命令&#xff0c;扩大…

Framework - ActivityThread 应用启动UI渲染流程

一、概念 ActivityThread拥有 main(String[] agrs) 方法&#xff0c;作为程序的入口&#xff0c;是应用程序的初始化类。&#xff08;ActivityThread不是主线程&#xff0c;它在 main() 方法中实例化&#xff0c;是运行在主线程中。&#xff09;ApplicationThread是 ActivityT…

MySQL 中 int(1) 和 int(10) 会影响存储的长度吗

一、MySQL 中 int(1) 和 int(10) 在MySQL数据库设计中&#xff0c;经常会遇到 int 类型的字段&#xff0c;并会习惯性的指定长度&#xff0c;比如&#xff1a; int(1) 和int(10)&#xff0c;而一些新手可能会误解它们之间的关系&#xff0c;认为 int(10) 能够存储更多的数据。…

项目开发 多行编辑

问题 项目开发中&#xff0c;如何进行多行编辑 详细问题 笔者使用IDEA&#xff0c;Android Studio进行项目开发时&#xff0c;由于代码冗余&#xff0c;修改过程中若是逐一删除或编辑&#xff0c;效率相对低&#xff0c;如何进行多行删除或编辑 本文将提供IDEA&#xff0c;A…

【深度学习】基于PyTorch架构神经网络学习总结(基础概念基本网络搭建)

神经网络整体架构 类似于人体的神经元 神经网络工作原来为层次结构&#xff0c;一层一层的变换数据。如上述示例有4层&#xff0c;1层输入层、2层隐藏层、1层输出层神经元&#xff1a;数据的量或矩阵的大小&#xff0c;如上述示例中输入层中有三个神经元代表输入数据有3个特征…

C语言中的指针详解

大家好&#xff0c;今天给大家介绍C语言中的指针详解&#xff0c;文章末尾附有分享大家一个资料包&#xff0c;差不多150多G。里面学习内容、面经、项目都比较新也比较全&#xff01;可进群免费领取。 **指针是C语言中的一个重要概念&#xff0c;它提供了一种直接访问内存地址…

某赛通电子文档安全管理系统 UploadFileToCatalog SQL注入漏洞复现

0x01 产品简介 某赛通电子文档安全管理系统(简称:CDG)是一款电子文档安全加密软件,该系统利用驱动层透明加密技术,通过对电子文档的加密保护,防止内部员工泄密和外部人员非法窃取企业核心重要数据资产,对电子文档进行全生命周期防护,系统具有透明加密、主动加密、智能…

Redis——事件

Redis服务器是一个事件驱动程序&#xff0c;服务器需要处理以下两种事件&#xff1a; 文件事件(file event)&#xff1a;Redis服务器通过套接字与客户端(或者其他Redis服务器)进行连接&#xff0c;而文件事件就是服务器对套接字操作的抽象(linux下一切皆文件&#xff0c;返回的…

unity角色触摸转向

1、挂载脚本到角色的父物体A上 2 、以屏幕左边的触摸为移动&#xff0c;右边为转向操作 3、加载角色时&#xff0c;将角色的父物体设置为A&#xff0c;须将角色的位置和角度置0 using System; using System.Collections; using System.Collections.Generic; using UnityEngin…

【C++初阶】--入门基础(二)

目录 一.C输出与输入 二.缺省参数 1.概念 2.缺省参数分类 (1) 全缺省参数 (2)半缺省参数 三.函数重载 1.概念 2.C支持函数重载的原理--名字修饰 四.引用 1.概念 2.语法 3.引用的特性 (1)引用在定义时必须初始化 (2)引用时不能改变指向 (3)一个变量…

Faster-Whisper 实时识别电脑语音转文本

Faster-Whisper 实时识别电脑语音转文本 前言项目搭建环境安装Faster-Whisper下载模型编写测试代码运行测试代码实时转写脚本 参考 前言 以前做的智能对话软件接的Baidu API&#xff0c;想换成本地的&#xff0c;就搭一套Faster-Whisper吧。 下面是B站视频实时转写的截图 项…

Vite与Webpack打包内存溢出问题优雅处理方式

Vite与Webpack打包内存溢出问题处理 文章目录 Vite与Webpack打包内存溢出问题处理1. Vite1. 打包错误提示2. 命令行方式解决3. 配置环境变量方式解决1. 设置变量2. 配置系统的环境变量 2. Webpack1. 打包错误提示2. 命令行方式解决3. 配置环境变量方式解决1. 设置变量2. 配置系…