Java双向链表基本功能实现[增删改查]

本文介绍了如何实现一个双链表,包括在任意位置添加元素、查找元素、修改元素值和删除元素的功能。代码示例展示了双链表的数据结构和相关操作方法,如addIndex、get、set和removeIndex等,并通过测试用例验证了其正确性。
摘要由CSDN通过智能技术生成
  • 添加节点 addIndex(int index,int val);在双链表任意index位置添加元素val     ps:找待插入位置的前驱节点,后继节点
  • 查找元素 get(int index);根据 inedx 查找对应的元素节点值;
  • 修改节点 set(int index,int newVal);当前链表中索引为 index 的节点值改为newVal;
  • 删除节点 removeIndex(int index);删除双链表中指定索引对应的元素节点;

草稿图纸 👇: 

 

代码 👇

package seqlist.doublelink;

public class DoubleLinkedList {
    private int size; // 当前链表有效元素个数
    private Node head; // 头节点
    private Node tail; // 尾节点

    /**
     * 头插
     * @param val
     */
    public void addFirst(int val){
        Node node = new Node(null,val,head);
        if (head==null){
            tail = node; // 当前链表为空
        }else{
            //当前链表不为空
            head.prev=node;
        }
        // 无论链表是否为空,最后node节点都是最新的头节点
        head = node;
        size++;
    }

    /**
     * 尾插
     * @param val
     */
    public void addLast(int val){
        Node node = new Node(tail,val,null);
        if (tail==null){
            head=node;
        }else{
            tail.next=node;
        }
        tail=node;
        size++;
    }

    /**
     * 找到index索引对应的节点
     * @param index
     * @return index对应的节点Node
     */
    private Node node(int index){
        Node ret = null;
        // index < size / 2(从头找)
        if (index < (size >> 1)){
            ret = head;
            for (int i = 0; i < index; i++) {
                ret = ret.next;
            }
        }else{
            // 此时从后向前遍历
            ret = tail;
            for (int i = size - 1; i > index; i--) {
                ret = ret.prev;
            }
        }
        return ret;
    }

    /**
     * 在index插入元素val
     * @param index
     * @param val
     */
    public void addIndex(int index,int val){
        if (index<0 || index>size){
            System.err.println("add index illegal!");
            return;
        }else if (index == 0) addFirst(val);
        else if (index == size) addLast(val);
        else {
            // 在中间位置插入,找到index的前驱节点
            // 找到index索引对应的节点后 写成方法 node
            Node prev = node(index-1);
            // 连接四根线
            Node newNode = new Node(prev,val,prev.next);
            prev.next.prev = newNode;
            prev.next = newNode;
            size++;
        }
    }

    /**
     * 检验index下标合法性
     * 适用于 查找,修改,删除 index下标元素
     * @param index
     * @return
     */
    public boolean rangeIndex(int index){
        if (index < 0 || index >= size){
            return false;
        }
        return true;
    }

    /**
     * 查找index下标元素
     * @param index
     * @return
     */
    public int get(int index){
        if (rangeIndex(index)){
            return node(index).val;
        }else {
            System.out.println("get index illegal!");
            return -1;
        }
    }

    /**
     * 判断链表里边是否存在与 val 相等的元素
     * @param val
     * @return
     */
    public boolean contains(int val){
        for (Node x = head;x!=null;x=x.next){
            if (x.val==val){
                return true;
            }
        }
        return false;
    }

    /**
     * 根据index修改元素值
     * @param index
     * @param newVal
     * @return 修改前的值
     */
    public int set(int index,int newVal){
        if (rangeIndex(index)){
            Node node = node(index);
            int oldVal = node.val;
            node.val = newVal;
            return oldVal;
        }else{
            System.err.println("set index illegal!");
            return -1;
        }
    }

    /**
     * 在双向链表中删除指定的node节点
     * @param node
     */
    private void unlink(Node node){
        // 分治思想
        Node prev = node.prev;
        Node next = node.next;
        // 先处理前驱节点
        if (prev == null){ // 此时是个头节点
            head = next;
        }else{
            // 有前驱
            prev.next = next;
            node.prev = null;
        }
        // 此时接着处理后半边的情况
        if (next == null){ // 此时node是个尾节点
            tail = prev;
        }else{
            next.prev = prev;
            node.next = null;
        }
        size--;
    }

    /**
     * 删除指定index下标元素
     * @param index
     */
    public void removeIndex(int index){
        if (rangeIndex(index)){
            Node node = node(index);
            unlink(node);
        }else{
            System.err.println("remove index illegal!");
        }
    }

    /**
     * 删除头节点
     */
    public void removeFirst() {
        removeIndex(0);
    }

    /**
     * 删除尾节点
     */
    public void removeLast() {
        removeIndex(size - 1);
    }


    public String toString(){
        String ret = "";
        Node node = head;
        while (node != null){
            ret += node.val + "->";
            node = node.next;
        }
        ret += "NULL";
        return ret;
    }

    /**
     * 删除第一个值为val的元素节点
     * @param val
     */
    public void removeValueOnce(int val){
        // 找到待删除节点
        for (Node x=head;x!=null;x=x.next){
            if (x.val==val){
                unlink(x);
                break;
            }
        }
    }

    /**
     * 删除所有值为val的元素节点
     * @param val
     */
    public void removeValueAll(int val){
        for (Node x=head;x!=null;){
            if (x.val==val){// x是待删除节点
                // next是下一个要判断的节点
                Node next = x.next;
                // 删除之后,x.next = x.prev = null
                unlink(x);
                x=next;
            }else{
                // 继续向后走
                x=x.next;
            }
        }
    }

    }

/**
 * 双链表的节点类
 */
class Node{
    Node prev;   // 指向前驱节点
    int val;     // 保存具体值
    Node next;   // 指向后继节点

    public Node(int val){
        this.val = val;
    }

    public Node(Node prev,int val,Node next){
        this.prev = prev;
        this.val = val;
        this.next = next;
    }
}

测试类 👇

package seqlist.doublelink;

public class testDoubleLinkedList {
    public static void main(String[] args) {
        DoubleLinkedList linkedList = new DoubleLinkedList();
        linkedList.addLast(2);
        linkedList.addLast(9);
        linkedList.addLast(2);
        linkedList.addLast(2);
        linkedList.addLast(2);
        linkedList.addFirst(7);
        linkedList.addFirst(5);
        linkedList.addIndex(0,3);
        linkedList.addIndex(3,6);
        System.out.println(linkedList);//3->5->7->6->2->9->2->2->2->NULL
        linkedList.removeIndex(3);
        System.out.println(linkedList);//3->5->7->2->9->2->2->2->NULL
        linkedList.removeValueOnce(2);
        System.out.println(linkedList);//3->5->7->9->2->2->2->NULL
        linkedList.removeValueAll(2);
        System.out.println(linkedList);//3->5->7->9->NULL
        System.out.println(linkedList.get(1));//5
        linkedList.set(2,10);
        System.out.println(linkedList);//3->5->10->9->NULL
    }
}

本小节完^_^
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王嘻嘻-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值