良辰当五日,“双向链表”还 (Java篇)

04-11 1408阅读

本篇会加入个人的所谓鱼式疯言

❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言

而是理解过并总结出来通俗易懂的大白话,

小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的.

🤭🤭🤭可能说的不是那么严谨.但小编初心是能让更多人能接受我们这个概念 !!!

良辰当五日,“双向链表”还 (Java篇)

前言

小伙伴是不是在此之前学习过单向链表,什么是单向链表呢

用我们的专业术语就是: 单向不带头不循环链表

如果还不熟悉的小伙伴们可以点击下方链接进行学习哦 💖 💖 💖

单链表详解链接

而今天的主角是我们的双向链表,什么是双向链表呢,请听下文分解 💥 💥 💥

良辰当五日,“双向链表”还 (Java篇)

目录

  1. LinkedList
  2. 双向链表的实现
  3. LinedList 和 ArrayList 的异同

一. LinkedList

1. LinkedList 的简介

LinkedList 的底层是 双向链表结构

由于链表没有将元素存储在连续的空间 中,元素存储在单独的 节点 中,然后通过引用将 节点 连接起来了,因此在在任意位置 插入 或者 删除 元素时,不需要 搬移元素 ,效率比较 高 。

良辰当五日,“双向链表”还 (Java篇)

并且在我们Java的集合框架中,LinkedList 也实现了 List 接口

良辰当五日,“双向链表”还 (Java篇)

鱼式疯言

LinkedList 这个类有以下五个特点

  1. LinkedList 实现了 List 接口
  1. LinkedList 的底层使用了 双向链表
  1. LinkedList 没有实现 RandomAccess 接口,因此 LinkedList 不支持随机访问
  1. LinkedList 的任意位置 插入 和 删除 元素时效率比较高,时间复杂度为 O(1)
  1. LinkedList 比较适合任意位置插入的场景

了解了什么是 LinkedList 之后

宝子们是不是和小编一样对这个链表很感兴趣呢

下面来详细说明下他怎么使用吧 💕 💕 💕

1. 尾插数据

public class TestLinked {
    public static void main(String[] args) {
        List list=new LinkedList();
        list.add("钟少爷");
        list.add("郭男神");
        list.add("刘富帅");
        list.add("杰哥哥");
    }
}

良辰当五日,“双向链表”还 (Java篇)

这里利用 add() 对 链表 直接进行 尾插 数据

2.指定 index 插入数据

public class TestLinked {
    public static void main(String[] args) {
        List list=new LinkedList();
        list.add("钟少爷");
        list.add("郭男神");
        list.add("刘富帅");
        list.add(1,"杰哥哥");
    }
}

良辰当五日,“双向链表”还 (Java篇)

用 Java 重载 的特性,形成了 两个参数列表不同 的 add(),但方法名同名的方法,从而指定 index 插入数据

鱼式疯言

LinkedList 的 add() 方法是返回值类型是 boolean 类型

当插入 成功 时返回的是 true

插入 失败 返回是 false

3.删除 index 的数据

public class TestLinked {
    public static void main(String[] args) {
        List list=new LinkedList();
        list.add("钟少爷");
        list.add("郭男神");
        list.add("刘富帅");
        list.add(1,"杰哥哥");
        System.out.println(list.remove(3)); // 删除 "刘富帅"
        System.out.println(list.remove(0)); // 删除 "钟少爷"
    }
}

良辰当五日,“双向链表”还 (Java篇)

利用 List类 中 remove() 可以 删除数据 并带出该数据的 返回值

4.得到 index 数据

public class TestLinked {
    public static void main(String[] args) {
        List 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));  // "刘富帅"
    }
}

良辰当五日,“双向链表”还 (Java篇)

我们可以利用 get() 根据我们输入的 index 得到我们需要的 数据 💥 💥 💥

public class TestLinked {
    public static void main(String[] args) {
        List 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));
    }
}

良辰当五日,“双向链表”还 (Java篇)

在此处我们可以通过 set() 修改 index 位置的值 , 并返回修改前 index 的值

5. 查找数据

public class TestLinked {
    public static void main(String[] args) {
        List 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("未找到该数据,查找失败!");
        }
    }
}

良辰当五日,“双向链表”还 (Java篇)

在这段代码块中

我们通过 contains() 方法搜寻 LinkedList 是否含有该数据

如果存在就返回其 下标 值

不存在就打印 提示信息

鱼式疯言

contains 返回类型: Boolean ,

如果存在就返回 true

不存在就返回 false

说完了LinkedList 的主要方法,我们就不妨动手实现这个双向链表吧 💖 💖 💖

二.双向链表的实现

1. 基本框架

我们首先定义一个 内部类 ,我们可以通过 内部类 来实现我们的一个个 节点 的窗帘

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.插入数据

良辰当五日,“双向链表”还 (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;
}

. 尾插数据

良辰当五日,“双向链表”还 (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;
}

. index 插入数据

良辰当五日,“双向链表”还 (Java篇)

public  void checkIndex(int index) throws IndexOutOfBoundsException{
    if (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  

良辰当五日,“双向链表”还 (Java篇)

3. 查找数据

    // 坚持是否包含 key
    @Override
    public boolean contains(int key) {
        LinkedNode cur=head;
        for (int i = 0; i  

良辰当五日,“双向链表”还 (Java篇)

4. 删除数据

良辰当五日,“双向链表”还 (Java篇)

. 移除 key 一个数据

    // 移除一个 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;
    }

. 移除所有 key 的数据

    // 移除所以 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;
        }
    }

良辰当五日,“双向链表”还 (Java篇)

5. 其他处理

. 获取链表大小

// 双链表长度
@Override
public int size() {
    int count=0;
    LinkedNode cur=head;
    while (cur !=null) {
        count++;
        cur=cur.next;
    }
    return  count;
}
 

良辰当五日,“双向链表”还 (Java篇)

这里只需要遍历链表 N 次 得到链表大小

. 释放链表

  // 释放双链表
    @Override
    public void clear() {
        LinkedNode cur=head;
        while (cur !=null) {
           LinkedNode tmp=cur.next;
//           cur.val=null;
           cur=null;
           cur=tmp;
        }
        head=null;
    }

良辰当五日,“双向链表”还 (Java篇)

逻辑代码展示

. main 函数代码

package Testdmo4.one;
import java.util.LinkedList;
import java.util.List;
public class TestLinked {
    public static void main(String[] args) {
        List 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("未找到该数据,查找失败!");
        }
    }
}

. 接口代码

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 的异同

良辰当五日,“双向链表”还 (Java篇)

鱼式疯言

总之一句话:

顺序表啥都 连续 ,链表只是 物理空间不连续

顺序表适合访问 和 尾插 和 尾删 ,链表适合 任意插入 和 删除

若有感兴趣的小伙伴可以优化我们的数据类型哦 💖 💖 💖

总结

  1. LinkedList : 理解LinkedList 的底层就是我们的双向链表
  2. 双向链表的实现: 我们用前后引用和内部类的实现了我们的链表
  3. LinedList 和 ArrayList 的异同: 清楚了 LinkedList 和 ArrayList 的各自的优势和使用场景

可谓收获颇丰啊 💖 💖 💖 💖

如果觉得小编写的还不错的咱可支持 三连 下 ==(定有回访哦) == , 不妥当的咱请评论区 指正

希望我的文章能给各位宝子们带来哪怕一点点的收获就是 小编 创作 的最大 动力 💖 💖 💖

良辰当五日,“双向链表”还 (Java篇)

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]