链表的补充——双链表

目录

一、双链表的定义

二、双向链表——插

1、双向链表头插

(1)、头插图解思路

(2)、头插代码实现

2、双向链表的尾插

(1)、尾插图解

 (2)、尾插代码实现

3、双向链表在index位置插入

(1)index位置插入图解

(2)index位置插入代码

二、双向链表——查找

三、双向链表——修改

 四、双向链表——删除

·1、删除双向链表中索引为index的节点

(1)删除index节点图解

 2、删除index节点的代码

2、双向链表删除第一个值为val的节点

3、双向链表删除所有值为val的节点

五、双向链表的全部代码


一、双链表的定义

对于链表中的任意节点,既可以通过该节点向后走,也可以通过该节点向前走

就是说相较于单链表多存储了该节点前面节点的地址

双向链表的实际应用中非常广泛

二、双向链表——插

1、双向链表头插

(1)、头插图解思路

(2)、头插代码实现

 /**
     * 双向链表的头插
     * @param val
     */
    public void addFirst(int val){
        doubleNode node=new doubleNode(val);
        //判断链表是否为空
        if (head==null){
            head=tail=node;
        }else{
            node.next=head;
            head.prev=node;
            head=node;
        }
        size++;
    }

2、双向链表的尾插

(1)、尾插图解

 (2)、尾插代码实现

 /**
     * 双向链表的尾插
     * @param val
     */
    public void addLast(int val){
        doubleNode node=new doubleNode(val);
        if (head==null){
            head=node;
        }else{
            tail.next=node;
            node.prev=tail;
            tail=node;
        }
        size++;
    }

3、双向链表在index位置插入

(1)index位置插入图解

(2)index位置插入代码

  /**
     * 双向链表在索引位置插入值为val的节点
     * @param index
     * @param val
     */
    public void add(int index,int val){
        //判断index是否合法
        if (index<0||index>size){
            System.err.println("index不在范围内");
            return;
        }
        if (index==0){
            //相当于头插
            addFirst(val);
        }else if (index==size){
            //相当于尾插
            addLast(val);
        }else{
            //利用方法找到前驱,前驱在index-1的位置
            doubleNode prev=findNode(index-1);
            doubleNode node=new doubleNode(val);
            node.next=prev.next;
            prev.next.prev=node;
            node.prev=prev;
            prev.next=node;
            size++;
        }
    }
    /**
     * 根据索引值寻找对应的节点
     * @param index
     * @return
     */
    private doubleNode findNode(int index){
        doubleNode x=null;
        if (index<size){
            x=head;
            for (int i = 0; i <index; i++) {
                x=x.next;
            }
        }else{
            x=tail;
            for (int i =index; i <size-1; i--) {
                x=x.prev;
            }
        }return x;
    }

二、双向链表——查找

public int get(int index):查找索引为index的节点值,返回节点值

/**
     * 查找索引为index的节点值,返回节点值
     * @param index
     * @return
     */
    public int  get(int index){
        //判断index的合法性
        if (judgeIndex(index)){
          doubleNode x=findNode(index);
          return x.val;
        }

        return -1;
    }
    /**
     * 判断index是否合法
     * @param index
     * @return
     */
    private boolean judgeIndex(int index){
        if (index<0||index>=size){
            return false;
        }
        return true;
    }
    /**
     * 根据索引值寻找对应的节点
     * @param index
     * @return
     */
    private doubleNode findNode(int index){
        doubleNode x=null;
        if (index<size){
            x=head;
            for (int i = 0; i <index; i++) {
                x=x.next;
            }
        }else{
            x=tail;
            for (int i =index; i <size-1; i--) {
                x=x.prev;
            }
        }return x;
    }

三、双向链表——修改

public int set(int index,int val):修改索引为index的节点值为val,返回修改前的值

  /**
     * 修改索引为index位置的节点值为val,返回修改前的值
     * @param index
     * @param val
     * @return
     */
    public int set(int index,int val){
        //判断index的合法性
        if (judgeIndex(index)){
            doubleNode x=findNode(index);
            int oldVal=x.val;
            x.val=val;
            return oldVal;

        }
        return -1;
    }
    /**
     * 判断index是否合法
     * @param index
     * @return
     */
    private boolean judgeIndex(int index){
        if (index<0||index>=size){
            return false;
        }
        return true;
    }
    /**
     * 根据索引值寻找对应的节点
     * @param index
     * @return
     */
    private doubleNode findNode(int index){
        doubleNode x=null;
        if (index<size){
            x=head;
            for (int i = 0; i <index; i++) {
                x=x.next;
            }
        }else{
            x=tail;
            for (int i =index; i <size-1; i--) {
                x=x.prev;
            }
        }return x;
    }

 四、双向链表——删除

·1、删除双向链表中索引为index的节点

(1)删除index节点图解

 2、删除index节点的代码

 /**
     * 删除链表中索引为index的节点
     * @param index
     */
    public void removeIndex(int index){
        //判断index是否合法
        if (judgeIndex(index)){
            doubleNode node=findNode(index);
            removeNode(node);
        }else{
            System.err.println("index不在范围内");
        }
    }
    /**
     * 删除当前链表中的node节点
     * @param node
     */
    public void removeNode(doubleNode node){
        doubleNode prev=node.prev;
        doubleNode successor=node.next;
        //1.先处理node的前半部分
        //判断前驱是否为空,为空则是删除头节点
        if (prev==null){
            head=successor;
        }else{
            //此时前驱不为空
            prev.next=successor;
            node.prev=null;
        }
        //2.在处理node的后半部分
        //判断后继节点是否为空,相当于删除尾节点
        if (successor==null){
            tail=prev;
        }else{
            //此时后继节点不为空
            successor.prev=prev;
            node.next=null;
        }
        size--;
    }
    /**
     * 根据索引值寻找对应的节点
     * @param index
     * @return
     */
    private doubleNode findNode(int index){
        doubleNode x=null;
        if (index<size){
            x=head;
            for (int i = 0; i <index; i++) {
                x=x.next;
            }
        }else{
            x=tail;
            for (int i =index; i <size-1; i--) {
                x=x.prev;
            }
        }return x;
    }

2、双向链表删除第一个值为val的节点

 /**
     * 删除链表中第一和值为val的节点
     */
    public void removeValOnce(int val){
        for (doubleNode x=head;x!=null;x=x.next) {
            if (x.val==val){
                removeNode(x);
                break;
            }
        }
    }

3、双向链表删除所有值为val的节点

 /**
     * 删除链表中所有值为val的节点
     */
    public void removeAllVal(int val){
        for (doubleNode x=head;x!=null;) {
            if (x.val==val){
                //此时x是待删除的点,同时保存一下x的后继节点的地址
                doubleNode successor=x.next;
                removeNode(x);
                x=successor;
            }else{
                //此时x已经不是待删除的点了,这是让for循环继续向下判断
                x=x.next;
            }
        }
    }

五、双向链表的全部代码

https://gitee.com/ren-xiaoxiong/rocket_class_ds/blob/master/src/linkedList/DoubleLinkedList.java

https://gitee.com/ren-xiaoxiong/rocket_class_ds/blob/master/src/linkedList/doubleLinkedTest.java 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值