【双向链表】java代码实现

前言:
大家好,我是良辰丫,上一篇文章我和大家一起去探索了单链表的知识世界,今天我们去接触双向链表,什么?没听错,就是双向链表,比单链表更炫酷的一种链表,首先祝大家新年快乐,新年新气象,希望大家能够在新的一年心想事成。然后请跟随我的脚步,去学习了解双向链表。。

个人主页:良辰针不戳
所属专栏:java数据结构
励志语句:生活也许会让我们遍体鳞伤,但最终这些伤口会成为我们一辈子的财富。
期待大家三连,关注,点赞,收藏。
作者能力有限,可能也会出错,欢迎大家指正。
愿与君为伴,共探Java汪洋大海。


目录

  • 双向链表
    • 1、双向链表的结构
    • 2、双向链表的基本操作
      • 2.1 头插法
      • 2.2 尾插法
      • 2.3 任意位置插入
      • 2.4 查找是否包含关键字key是否在双向链表当中
      • 2.5 删除第一次出现关键字为key的节点
      • 2.6 删除所有值为key的节点
      • 2.7 获取双向链表的长度
      • 2.8 打印双向链表数据
      • 2.9 清空双向链表数据


双向链表

1、双向链表的结构

在双向链表中一个数据域会分散出两个指针域,一个pre指针指向上一个数据的地址,一个next指针指向下一个数据的地址。

【双向链表】java代码实现_第1张图片

下面为一个双向链表结构图,可能画的图有些抽象哈哈,是每个指针指向它所指的节点。

【双向链表】java代码实现_第2张图片

2、双向链表的基本操作

2.1 头插法

首先申请一个节点(基本套路),头结点为空时,说明双向链表中没有数据,那么头指针和尾指针都指向新节点。

【双向链表】java代码实现_第3张图片

头结点不为空时,进行头插操作,我们前面说过后绑思想,node节点先与头结点进行绑定。双向链表头插法比较特殊,两个指针,我们可以不按照后绑思想(还是建议大家就使用后绑思想,不容易出错),绑定完成后,不要忘了头指针前移。

【双向链表】java代码实现_第4张图片

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

2.2 尾插法

  • 双向链表尾插法时间复杂度为O(1),因为双向链表有尾指针,不用通过遍历寻找尾巴。
  • 头结点为空时,直接让头指针和尾指针指向头结点。
  • 然后通过尾指针进行连接操作。
  • 最后尾指针后移。

【双向链表】java代码实现_第5张图片

//尾插法 O(1)
    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;
        }
    }

2.3 任意位置插入

  • 插入位置不合法直接退出。
  • 在第一个位置插入直接调用头插法。
  • 在最后一个位置插入直接调用尾插法。
  • 其它情况找到要插入的位置下标,还是采用后绑法,分为四步进行插入,大家灵活掌握哦!

【双向链表】java代码实现_第6张图片

//任意位置插入
    public void addIndex(int index,int data){
        if(index < 0 || index > size()) {
            return ;
        }
        if(index == 0) {
            addFirst(data);
            return;
        }
        if(index == size()) {
            addLast(data);
            return;
        }

        ListNode cur = findIndex(index);
        //
        ListNode node = new ListNode(data);
        node.next = cur;
        cur.prev.next = node;
        node.prev = cur.prev;
        cur.prev = node;

    }
    private ListNode findIndex(int index) {
        ListNode cur = head;
        while (index != 0) {
            cur = cur.next;
            index--;
        }
        return cur;
    }

2.4 查找是否包含关键字key是否在双向链表当中

查找关键词其实和单链表一样,遍历一次找到返回true,找不到返回false。

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

2.5 删除第一次出现关键字为key的节点

public void remove(int key){
        ListNode cur = head;
        while (cur != null) {
            //开始删除了
            if(cur.val == key) {
                //1. 删除的是头节点
                if(cur == head) {
                    head = head.next;
                    //只有一个节点
                    if(head != null) {
                        head.prev = null;
                    }
                }else {
                    //中间  尾巴
                    cur.prev.next = cur.next;
                    //不是尾巴节点
                    if(cur.next != null) {
                        cur.next.prev = cur.prev;
                    }else {
                        //是尾巴节点
                        last = last.prev;
                    }
                }
                return;
            }
            cur = cur.next;
        }
    }

2.6 删除所有值为key的节点

//删除所有值为key的节点
    public void removeAllKey(int key){
        ListNode cur = head;
        while (cur != null) {
            //开始删除了
            if(cur.val == key) {
                //1. 删除的是头节点
                if(cur == head) {
                    head = head.next;
                    //只有一个节点
                    if(head != null) {
                        head.prev = null;
                    }
                }else {
                    //中间  尾巴
                    cur.prev.next = cur.next;
                    //不是尾巴节点
                    if(cur.next != null) {
                        cur.next.prev = cur.prev;
                    }else {
                        //是尾巴节点
                        last = last.prev;
                    }
                }
            }
            cur = cur.next;
        }
    }

2.7 获取双向链表的长度

和单链表一样,遍历一次,记录元素个数。

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

2.8 打印双向链表数据

遍历一次双向链表,依次打印数据。双向链表有前驱指针,因此也可以倒着打印。

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

2.9 清空双向链表数据

遍历一次链表,释放所有指针指向,注意释放前要保存next域,防止找不到下一个位置。当然了,也可以通过粗鲁的释放,直接释放首尾节点。

public void clear(){
        ListNode cur = head;
        while (cur != null) {
            ListNode curNext = cur.next;
            cur.prev = null;
            cur.next = null;
            cur = curNext;
        }
        head = null;
        last = null;
    }

后序:
双向链表的内容和单链表很相似,但是这里的任意位置插入刚开始学总会觉得有些奇怪,很正常的表现,其实没有大家想的那么难,多去思考,多去敲代码,你会有很好的收获!!!

你可能感兴趣的:(Java语言学习,【数据结构】Java编程语言,链表,java,数据结构)