【数据结构_6】双向链表的实现

一、实现MyDLinkedList(双向链表)

java 复制代码
package LinkedList;

public class MyDLinkedList {

    //首先我们要创建节点(因为双向链表和单向链表的节点不一样!!)
    static class Node{
        public String val;
        public Node prev = null;
        public Node next = null;
        //给一个构造方法

        public Node(String val) {
            this.val = val;
        }
    }
    //表示整个链表,此处不引入傀儡节点,使用Null表示空的链表
    public Node head = null;
    //为了方便后续的尾插曹祖
    public Node tail = null;

    //给一个toStirng的打印


    @Override
    public String toString() {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("[");
        //进行链表的遍历
        for(Node cur = head;cur!= null ;cur = cur.next){

           stringBuilder.append(cur.val);
           if(cur.next != null) {
               stringBuilder.append(",");
           }
        }
        stringBuilder.append("]");
        return stringBuilder.toString();
    }

    //接下来来实现一些双向链表的核心操作
    //1.实现头插操作
    public void addFirst(String val){
        Node newNode = new Node(val);
        //首先判断链表是否为空的情况
        if(head == null){
            head = newNode;
            tail = newNode;
        }else {
        //再来看看一般情况
        newNode.next = head;
        head. prev = newNode;
        //2.让head指向新节点
        head = newNode;
    }
    }

    //2.实现链表的尾插操作
    public void addLast(String val){
        Node newNode = new Node(val);
        //1.首先判断链表为空的情况,可知与头插操作一样
        if(head == null){
            head = newNode;
            tail = newNode;
        }else {
            //2.考虑一般情况
            tail.next = newNode;
            newNode.prev = tail;
            tail = newNode;
        }
    }

    //实现链表长度的计算
    public int size(){
        int size =0;
        for(Node cur = head;cur != null;cur = cur.next){
            size++;
        }
        return size;
    }

    //3.实现双向链表的按位置插入
    public void add(int index,String val){
        int size = size();
        //1.首先判断index的值是否合法
        if( index < 0 || index > size ){
            throw  new IndexOutOfBoundsException("Index:"+index+",Size:"+size);
        }
        //2.判断特殊位置
        if(index ==0 ){
            //此时就是头插操作
            addFirst(val);
            return;
        }
        if(index== size){
            //此时就是尾插
            addLast(val);
            return;
        }
        //3.进行一般的插入
        //先找到要插入节点的前一个节点
        Node prev = head;
        for(int i =0;i<index-1;i++){
            prev = prev.next;
        }
        //此时我们已经找到了要插入节点的前一个节点
        Node newNode = new Node(val);
        Node next = prev.next;
        //首先建立新节点与上一个节点之间的关系
        prev.next = newNode;
        newNode.prev = prev;
        //再建立新节点与下一个节点之间的关系
        newNode.next = next;
        next.prev = newNode;
    }

    //4.实现包含查找操作
    public Boolean contains(String val){
        for (Node cur = head ; cur != null;cur = cur.next){
            if(cur.val.equals(val)) {
                return true;
            }
        }
        return false;
    }

    //5.查找元素,返回该元素的下标,如果没有找到,返回-1
    public int indexOf(String val){
        int index =0;
        for (Node cur = head;cur != null;cur =cur.next){
            if(cur.val.equals(val)){
                return  index;
            }
            index++;
        }
        return -1;
    }

    //6.头删
    public void removeFirst(){
     //1.首先考虑是否为空链表
     if(head == null){
         return;//空链表无法进行删除操作
     }
     //2.考虑只有一个节点的情况
     if(head.next == null){
         head = null;
         tail = null;
         return;
     }
     //3.考虑一般情况
        head = head.next;
     head.prev = null;
    }

    //7.尾部删除
    public void removeLast(){
        //1.考虑空链表
        if (head == null){
            return;
        }
        //2.考虑只有一个节点
        if(head.next == null){
            head = null;
            tail = null;
            return;
        }
        //3.考虑一般情况
        tail = tail.prev;
        tail.next = null;
    }

    //8.指定位置删除
    public void remove(int index){
        int size = size();
        //对index做判断
        if(index <0 || index >= size){
            throw  new IndexOutOfBoundsException("index:"+index+",size:"+size);
        }
        //2.如果是删除index=0
        if(index ==0){
            removeFirst();
            return;
        }
        if(index ==size-1){
            removeLast();
            return;
        }
        //3.考虑一般情况的删除
        //先找到前一个节点
        Node prev = head;
        for(int i =0;i<index-1;index++){
            prev = prev.next;
        }
        Node toRemove = prev.next;
        Node next = toRemove.next;
        //4.进行删除操作
        prev.next = next;
        next.prev =prev;

    }

    //9.指定值删除
    public void remove(String val){
        //1.首先考虑空的链表
        if(head == null){
            return ;
        }
        //2.判定头删/尾删操作
        if(val.equals(head.val)){
            removeFirst();
            return;
        }
        if(val.equals(tail.val)){
            removeLast();
            return;
        }
        //3.一般情况 先找到前一个节点
        Node toRemove = head;
        for (;toRemove!=null;toRemove= toRemove.next){
            if(toRemove.val.equals(val)){
                break;
            }
        }
        //循环之外有两种情况一种是找到了打破循环 另一种是循环走完了!
        if(toRemove == null){
            return ;
        }

        Node prev = toRemove.prev;
        Node next = toRemove.next;
        prev.next = next;
        next.prev = prev;

    }

    //10.链表的清空操作
    public void clear(){
        head = null;
        tail = null;
    }


    public static void test(){
        MyDLinkedList list = new MyDLinkedList();
        list.addFirst("a");
        list.addFirst("b");
        list.addFirst("c");
        System.out.println(list);
    }

    public static  void test1(){
        MyDLinkedList list = new MyDLinkedList();
        list.addLast("c");
        list.addLast("b");
        list.addLast("a");
        System.out.println(list);
    }

    public static void test3(){
        MyDLinkedList list = new MyDLinkedList();
        list.addFirst("a");
        list.addFirst("a");
        list.addFirst("a");
        list.addFirst("a");
        list.add(0,"b");
        list.add(2,"c");
        System.out.println(list);
    }

    public static void test4(){
        MyDLinkedList list = new MyDLinkedList();
        list.addFirst("a");
        list.addFirst("a");
        list.addFirst("a");
        list.addFirst("a");
        list.add(0,"b");
        list.add(2,"c");
        System.out.println(list);

        System.out.println(list.indexOf("a"));
        System.out.println(list.contains("b"));
        System.out.println(list.contains("d"));

    }
    public static void test5() {
        MyDLinkedList list = new MyDLinkedList();
        list.addFirst("a");
        list.addFirst("a");
        list.addFirst("a");
        list.addFirst("a");
        list.add(0, "b");
        list.add(2, "c");
        System.out.println(list);
        list.removeFirst();
        list.removeFirst();
        System.out.println(list);
    }

    public static void test6() {
        MyDLinkedList list = new MyDLinkedList();
        list.addFirst("a");
        list.addFirst("a");
        list.addFirst("a");
        list.addFirst("a");
        list.add(0, "b");
        list.add(2, "c");
        System.out.println(list);
        list.removeLast();
        list.removeLast();
        System.out.println(list);
    }
    public static void test7() {
        MyDLinkedList list = new MyDLinkedList();
        list.addFirst("a");
        list.addFirst("a");
        list.addFirst("a");
        list.addFirst("a");
        list.add(0, "b");
        list.add(2, "c");
        System.out.println(list);
        list.remove(1);
        list.remove(4);
        System.out.println(list);
    }

    public static void test8() {
        MyDLinkedList list = new MyDLinkedList();
        list.addLast("a");
        list.addLast("b");
        list.addLast("c");
        System.out.println(list);
        list.remove("a");
        System.out.println(list);
    }
    public static void main(String[] args) {
      //  test();
       // test1();
        //test3();
       // test4();
        //test5();
        //test6();
        //test7();
        //test8();
    }
}
相关推荐
躺平大鹅2 小时前
Java面向对象入门(类与对象,新手秒懂)
java
初次攀爬者3 小时前
RocketMQ在Spring Boot上的基础使用
java·spring boot·rocketmq
花花无缺3 小时前
搞懂@Autowired 与@Resuorce
java·spring boot·后端
Derek_Smart5 小时前
从一次 OOM 事故说起:打造生产级的 JVM 健康检查组件
java·jvm·spring boot
NE_STOP5 小时前
MyBatis-mybatis入门与增删改查
java
孟陬9 小时前
国外技术周刊 #1:Paul Graham 重新分享最受欢迎的文章《创作者的品味》、本周被划线最多 YouTube《如何在 19 分钟内学会 AI》、为何我不
java·前端·后端
想用offer打牌9 小时前
一站式了解四种限流算法
java·后端·go
华仔啊9 小时前
Java 开发千万别给布尔变量加 is 前缀!很容易背锅
java
也些宝10 小时前
Java单例模式:饿汉、懒汉、DCL三种实现及最佳实践
java