本篇会加入个人的所谓鱼式疯言
❤️❤️❤️鱼式疯言
:❤️❤️❤️此疯言非彼疯言
而是理解过并总结出来通俗易懂的大白话,
小编会尽可能的在每个概念后插入鱼式疯言
,帮助大家理解的.
🤭🤭🤭可能说的不是那么严谨
.但小编初心是能让更多人能接受我们这个概念
!!!
前言
小伙伴是不是在此之前学习过单向链表,什么是单向链表呢
用我们的专业术语就是: 单向不带头不循环链表
如果还不熟悉的小伙伴们可以点击下方链接进行学习哦 💖 💖 💖
而今天的主角是我们的双向链表,什么是双向链表呢,请听下文分解 💥 💥 💥
目录
- LinkedList
- 双向链表的实现
- LinedList 和 ArrayList 的异同
一. LinkedList
1. LinkedList 的简介
LinkedList
的底层是 双向链表结构
由于链表没有将元素存储在连续的空间
中,元素存储在单独的节点
中,然后通过引用将节点
连接起来了,因此在在任意位置 插入 或者 删除 元素时,不需要 搬移元素 ,效率比较高
。
并且在我们Java的集合框架中,LinkedList
也实现了 List
接口
鱼式疯言
LinkedList 这个类有以下五个特点
LinkedList
实现了List
接口LinkedList
的底层使用了双向链表
LinkedList
没有实现RandomAccess
接口,因此LinkedList
不支持随机访问LinkedList
的任意位置 插入 和 删除 元素时效率比较高,时间复杂度为O(1)
LinkedList
比较适合任意位置插入的场景
了解了什么是 LinkedList 之后
宝子们是不是和小编一样对这个链表很感兴趣呢
下面来详细说明下他怎么使用吧 💕 💕 💕
1. 尾插数据
java
public class TestLinked {
public static void main(String[] args) {
List<String> list=new LinkedList<>();
list.add("钟少爷");
list.add("郭男神");
list.add("刘富帅");
list.add("杰哥哥");
}
}
这里利用 add()
对 链表 直接进行 尾插
数据
2.指定 index 插入数据
java
public class TestLinked {
public static void main(String[] args) {
List<String> list=new LinkedList<>();
list.add("钟少爷");
list.add("郭男神");
list.add("刘富帅");
list.add(1,"杰哥哥");
}
}
用 Java
重载
的特性,形成了 两个参数列表不同 的add()
,但方法名同名的方法,从而指定 index 插入数据
鱼式疯言
LinkedList
的add()
方法是返回值类型是 boolean 类型
当插入成功
时返回的是 true
插入失败
返回是 false
3.删除 index 的数据
java
public class TestLinked {
public static void main(String[] args) {
List<String> list=new LinkedList<>();
list.add("钟少爷");
list.add("郭男神");
list.add("刘富帅");
list.add(1,"杰哥哥");
System.out.println(list.remove(3)); // 删除 "刘富帅"
System.out.println(list.remove(0)); // 删除 "钟少爷"
}
}
利用 List类 中
remove()
可以删除数据
并带出该数据的返回值
4.得到 index 数据
java
public class TestLinked {
public static void main(String[] args) {
List<String> list=new LinkedList<>();
list.add("钟少爷");
list.add("郭男神");
list.add("刘富帅");
list.add(1,"杰哥哥");
System.out.println("====== 删除数据 ========");
System.out.println(list.remove(3)); // 删除 "刘富帅"
System.out.println(list.remove(0)); // 删除 "钟少爷"
System.out.println("======= 获取数据 ========");
System.out.println(list.get(0)); // "郭男神"
System.out.println(list.get(1)); // "刘富帅"
}
}
我们可以利用 get() 根据我们输入的
index
得到我们需要的 数据 💥 💥 💥
java
public class TestLinked {
public static void main(String[] args) {
List<String> list=new LinkedList<>();
list.add("钟少爷");
list.add("郭男神");
list.add("刘富帅");
list.add("吴富婆");
list.add(1,"杰哥哥");
System.out.println("====== 删除数据 ========");
System.out.println(list.remove(3)); // 删除 "刘富帅"
System.out.println(list.remove(0)); // 删除 "钟少爷"
System.out.println("======= 获取数据 ========");
System.out.println(list.get(0)); // "郭男神"
System.out.println(list.get(1)); // "刘富帅"
System.out.println("========= 修改数据 =========");
System.out.println(list.set(0, "彭于晏"));
System.out.println(list.get(0));
}
}
在此处我们可以通过 set() 修改
index
位置的值 , 并返回修改前index
的值
5. 查找数据
java
public class TestLinked {
public static void main(String[] args) {
List<String> list=new LinkedList<>();
list.add("钟少爷");
list.add("郭男神");
list.add("刘富帅");
list.add("吴富婆");
list.add(1,"杰哥哥");
System.out.println("====== 删除数据 ========");
System.out.println(list.remove(3)); // 删除 "刘富帅"
System.out.println(list.remove(0)); // 删除 "钟少爷"
System.out.println("======= 获取数据 ========");
System.out.println(list.get(0)); // "郭男神"
System.out.println(list.get(1)); // "刘富帅"
System.out.println("========= 修改数据 =========");
System.out.println(list.set(0, "彭于晏"));
System.out.println(list.get(0));
System.out.println("=========查找数据=========");
String s=new String("郭男神");
if (list.contains(s)) {
System.out.println("该数据的下标为:"+ list.indexOf(s));
} else {
System.out.println("未找到该数据,查找失败!");
}
}
}
在这段代码块中
我们通过
contains()
方法搜寻LinkedList
是否含有该数据
如果存在就返回其下标
值
不存在就打印 提示信息
鱼式疯言
contains
返回类型:Boolean
,
如果存在就返回true
不存在就返回false
说完了LinkedList 的主要方法,我们就不妨动手实现这个双向链表吧 💖 💖 💖
二.双向链表的实现
1. 基本框架
我们首先定义一个 内部类
,我们可以通过 内部类 来实现我们的一个个 节点
的窗帘
java
package linklist;
public class MyLinkedList extends AbLinkList{
public static class LinkedNode {
public LinkedNode prev;
public int val;
public LinkedNode next;
public LinkedNode(int val) {
this.val = val;
}
}
}
并在 内部类 的前提下,我们有了前驱节点
prev
数据val
以及后驱节点next
2.插入数据
<1>. 头插数据
java
public void addFirst(int data) {
LinkedNode node=new LinkedNode(data);
if (isEmpty()) {
head=last=node;
return;
}
head.prev=node;
node.next=head;
head=node;
}
<2>. 尾插数据
java
// 尾插数据
@Override
public void addLast(int data) {
LinkedNode node=new LinkedNode(data);
if (isEmpty()) {
head=last=node;
return;
}
last.next=node;
node.prev=last;
last=node;
}
<3>. index 插入数据
java
public void checkIndex(int index) throws IndexOutOfBoundsException{
if (index<0 || index > size()) {
throw new IndexOutOfBoundsException("下标异常!");
}
}
// 增加某位置的数据
@Override
public boolean addIndex(int index, int data) {
try {
checkIndex(index);
} catch (IndexOutOfBoundsException e) {
e.printStackTrace();
return false;
}
if (index==0) {
addFirst(data);
return true;
}
if (index==size()) {
addLast(data);
return true;
}
LinkedNode cur=head;
LinkedNode node=new LinkedNode(data);
for (int i = 0; i < index; i++) {
cur=cur.next;
}
cur.prev.next=node;
node.prev=cur.prev;
cur.prev=node;
node.next=cur;
return true;
}
3. 查找数据
java
// 坚持是否包含 key
@Override
public boolean contains(int key) {
LinkedNode cur=head;
for (int i = 0; i < size(); i++) {
if (cur.val==key) {
return true;
}
cur=cur.next;
}
return false;
}
4. 删除数据
<1>. 移除 key 一个数据
java
// 移除一个 key 数据
@Override
public boolean remove(int key) {
if (isEmpty()) {
return false;
}
if (head.val==key) {
// head.val=null;
head=head.next;
head.prev=null;
return true;
}
if (last.val==key) {
// last.val=null;
last=last.prev;
last.next=null;
return true;
}
LinkedNode cur= head;
while (cur !=null) {
if (cur.val==key) {
// cur.val=null;
cur.prev.next=cur.next;
cur.next.prev=cur.prev;
return true;
}
cur=cur.next;
}
return false;
}
<2>. 移除所有 key 的数据
java
// 移除所以 key 的数据
@Override
public void removeAllKey(int key) {
LinkedNode cur= head.next;
while (cur.next !=null) {
if (cur.val==key) {
// cur.val=null;
cur.prev.next=cur.next;
cur.next.prev=cur.prev;
}
cur=cur.next;
}
if (head.val==key) {
// head.val=null;
head=head.next;
head.prev=null;
}
if (last.val==key) {
// last.val=null;
last=last.prev;
last.next=null;
}
}
5. 其他处理
<1>. 获取链表大小
java
// 双链表长度
@Override
public int size() {
int count=0;
LinkedNode cur=head;
while (cur !=null) {
count++;
cur=cur.next;
}
return count;
}
这里只需要遍历链表 N
次 得到链表大小
<2>. 释放链表
java
// 释放双链表
@Override
public void clear() {
LinkedNode cur=head;
while (cur !=null) {
LinkedNode tmp=cur.next;
// cur.val=null;
cur=null;
cur=tmp;
}
head=null;
}
逻辑代码展示
<1>. main 函数代码
java
package Testdmo4.one;
import java.util.LinkedList;
import java.util.List;
public class TestLinked {
public static void main(String[] args) {
List<String> list=new LinkedList<>();
list.add("钟少爷");
list.add("郭男神");
list.add("刘富帅");
list.add("吴富婆");
list.add(1,"杰哥哥");
System.out.println(list);
System.out.println("====== 删除数据 ========");
System.out.println(list.remove(3)); // 删除 "刘富帅"
System.out.println(list.remove(0)); // 删除 "钟少爷"
System.out.println("======= 获取数据 ========");
System.out.println(list.get(0)); // "郭男神"
System.out.println(list.get(1)); // "刘富帅"
System.out.println("========= 修改数据 =========");
System.out.println(list.set(0, "彭于晏"));
System.out.println(list.get(0));
System.out.println("=========查找数据=========");
String s=new String("郭男神");
if (list.contains(s)) {
System.out.println("该数据的下标为:"+ list.indexOf(s));
} else {
System.out.println("未找到该数据,查找失败!");
}
}
}
<2>. 接口代码
java
package linklist;
public abstract class AbLinkList {
//头插法
public abstract void addFirst(int data);
//尾插法
public abstract void addLast(int data);
//任意位置插入,第一个数据节点为0号下标
public abstract boolean addIndex(int index,int data);
//查找是否包含关键字key是否在单链表当中
public abstract boolean contains(int key);
//删除第一次出现关键字为key的节点
public abstract boolean remove(int key);
//删除所有值为key的节点
public abstract void removeAllKey(int key);
//得到双链表的长度
public abstract int size();
// 打印双链表
public abstract void display();
// 释放双链表
public abstract void clear();
}
三. LinedList 和 ArrayList 的异同
鱼式疯言
总之一句话:
顺序表啥都 连续 ,链表只是 物理空间不连续。
顺序表适合访问 和尾插
和尾删
,链表适合 任意插入 和 删除
若有感兴趣的小伙伴可以优化我们的数据类型哦 💖 💖 💖
总结
- LinkedList : 理解LinkedList 的底层就是我们的双向链表
- 双向链表的实现: 我们用前后引用和内部类的实现了我们的链表
- LinedList 和 ArrayList 的异同: 清楚了 LinkedList 和 ArrayList 的各自的优势和使用场景
可谓收获颇丰啊 💖 💖 💖 💖
如果觉得小编写的还不错的咱可支持 三连 下 ==(定有回访哦) == , 不妥当的咱请评论区 指正
希望我的文章能给各位宝子们带来哪怕一点点的收获
就是 小编 创作 的最大 动力 💖 💖 💖