[数据结构]java双链表实现增删查改基础操作

双链表实现增删查改基础操作

//Sequence.java
public interface Sequence {//接口
    /**
     * 向线性表中添加元素
     * @param data 要存储的元素
     */
    void add(Object data);

    /**
     * 线性表中删除元素
     * @param index 要删除的元素下标
     * @return 是否删除成功
     */
    boolean remove(int index);

    /**
     * 在线性表中查找指定索引的元素
     * @param index 要查找的索引
     * @return
     */
    Object get(int index);

    /**
     * 判断线性表中是否有指定元素
     * @param data 要查找的元素内容
     * @return
     */
    boolean contains(Object data);

    /**
     * 修改线性表中指定索引的内容
     * @param index 要修改的元素下标
     * @param newData 修改后的内容
     * @return
     */
    Object set(int index,Object newData);

    /**
     * 返回当前线性表元素个数
     * @return
     */
    int size();

    /**
     * 直接清空线性表内容
     */
    void clear();

    /**
     * 将线性表转为数组
     * @return
     */
    Object[] toArray();
}

//DoubleLinkList.java
public class DoubleLinkList implements Sequence{//类实现接口(小彩蛋 覆写接口所有类的快捷方法为:将光标放置本行Sequence后,按ALT+ENTER键一路向下即可)
    private Node head;//头节点
    private Node tail;//尾节点
    private int size;//链表长度
    class Node{//节点类
        Node prev;//前驱指针
        Object data;//数据
        Node next;//后继指针         

        public Node(Node prev, Object data, Node next) {
            this.prev = prev;
            this.data = data;
            this.next = next;
        }

        public Node(Object data) {
            this.data = data;
        }
    }
    public void add(Object data){//增加操作(采用尾插法)
        Node newNode=new Node(tail,data,null);
        if(head==null){
            head=newNode;
        }else {
            tail.next=newNode;
        }
        tail=newNode;
        size++;
    }

    @Override
    public boolean remove(int index) {//删除操作
        if(head==null){
            return false;
        }
        rangeCheck(index);//判断下标是否合理
        Node cur=node(index);//确定当前下标节点
        Node next=cur.next;//当前节点后继指针
        Node prev=cur.prev;//当前节点前驱指针
        //删除节点最复杂情况为删除中间节点(即需要重新调整四个指针关系),故先看左边再看右边判断
        if(prev==null){
            head=next;
        }else{
            prev.next=next;
            prev=null;
        }
        if(next==null){
            tail=prev;
        }else{
            next.prev=prev;
            next=null;
        }
        size--;
        return false;
    }

    @Override
    public Object get(int index) {//获得特定下标节点
        rangeCheck(index);
        return node(index).data;//返回节点数据
    }

    @Override
    public boolean contains(Object data) {//查看链表中是否有特定元素
        if(head==null){
            return false;
        }
        Object[] array=toArray();
        for(int i=0;i<array.length;i++){
            if(array[i]==data){
                return true;
            }
        }
        return false;
    }

    @Override
    public Object set(int index, Object newData) {//替换特定节点元素,并返回原节点数据
        rangeCheck(index);
        Node node=node(index);
        Object oldData=node.data;
        node.data=newData;
        return oldData;
    }

    @Override
    public int size() {//链表长度
        return this.size;
    }

    @Override
    public void clear() {//清空
        for(Node temp=head;temp!=null;temp=temp.next){
            if(head.next!=null){//判断是否下一个节点为空
                head=head.next;//先将头节点移动至下一节点,保证后面节点存在
                temp.data=null;
            }else{//若为空则只有一个节点(置空数据即可,因头节点前驱指针本来就指向Null,尾节点后继节点也如此)
                head.data=null;
            }
            size--;
        }
    }

    @Override
    public Object[] toArray() {//链表转变为数组
        Object[] data=new Object[size];
        int i=0;
        for(Node temp=head;temp!=null;temp=temp.next){
            data[i++]=temp.data;
        }
        return data;
    }
    private void rangeCheck(int index){//判断下标是否合理
        if(index<0||index>=size){
            throw new IndexOutOfBoundsException("下标越界异常");
        }
    }
    private Node node(int index){//采用从前到后或从后到前的方法寻找某下标节点
        //查找指定下标节点,因双链表可从前至后遍历也可从后至前遍历,故我们可从中间下标划分,之前的从前至后遍历,之后的从后至前遍历,减少遍历次数
        if(index<size>>1){
            Node cul=head;
            for(int i=0;i<index;i++){
                cul=cul.next;
            }
            return cul;
        }else{
            Node cull=tail;
            for(int i=size-1;i>index;i--){
                cull=cull.prev;
            }
            return cull;
        }
    }
    public void display(){
        for(Node temp=head;temp!=null;temp=temp.next){
            System.out.print(temp.data+" ");
        }
    }
}

//Test.java
public class Test {
    public static void main(String[] args) {
        DoubleLinkList doubleLinkList=new DoubleLinkList();
        doubleLinkList.add(1);
        doubleLinkList.add(2);
        doubleLinkList.add(3);
        doubleLinkList.add(4);
        doubleLinkList.add(5);
        doubleLinkList.display();//增加节点输出
        System.out.println();
        System.out.println(doubleLinkList.size());//测试链表长度
        System.out.println("-----------------------");
        System.out.println(doubleLinkList.get(1));//测试取得指定下标节点
        System.out.println(doubleLinkList.get(3));
        System.out.println("-----------------------");
        System.out.println(doubleLinkList.get(1));
        doubleLinkList.set(1,100);//替换指定下标节点数据
        System.out.println(doubleLinkList.get(1));//测试是否替换成功
        System.out.println("-----------------------");
        doubleLinkList.remove(0);//移除指定下标节点
        System.out.println(doubleLinkList.size());//测试是否移除成功
        System.out.println("-----------------------");
        System.out.println(doubleLinkList.contains(3));//测试链表中是否存在指定数据
        System.out.println(doubleLinkList.contains(90));
        System.out.println("-----------------------");
        doubleLinkList.clear();//清空
        System.out.println(doubleLinkList.size());//测试是否清空
    }
}

添加节点图解:

在这里插入图片描述

删除节点图解:

在这里插入图片描述

运行结果:

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_42617262/article/details/88306339
今日推荐