双向链表java代码实现(带头结点和尾结点)

考虑到单向链表的缺点,所有节点的遍历都是从头结点开始,若一条记录居于整个链表的结尾,当要查询该记录效率就会比较低,采用双向链表,会更具有扩展性;

在实现过程的整体思路,定义一个链表类,在其中定义一个节点类,在链表类定义头和尾结点的构造方法中创建结点对象,使其头节点的next指向尾结点,尾结点的prenode 指向head,进行链表的初始化。接着就相对简单,定义增加,删除,修改,查询等方法。

注意的细节问题:无论是增加一个节点,还是删除一个节点都应该注意考虑prenode 的指向,否则在从后向前遍历的过程中,JVM会抛出空指针异常,在根据内容相同删除节点时,若两个数据处于相邻的情况,考虑删除数据的正确性,节点的遍历与索引的自增并不同步,会造成删除的数据有误,每次在删除节点后,遍历节点的变量应该减1。

public class DoubleLinkedDemo {
    static class DoubleLinked<T>{
        private class Node<T>{
            Node<T> prenode ;
            T value;
            Node<T> next;
            public Node(){};
            public Node(T value){
                this.value = value;
            }
        }
        private Node<T> head;
        private Node<T> end;
        private int size;
        public DoubleLinked(){
            this.head = new Node<>();
            this.end = new Node<>();
            head.next = end;
            end.prenode= head;
            this.size = 0;
        }
        //从前往后追加一个节点
        public void preadd(T value){
            Node<T> newnode = new Node<>(value);
            int i =0;
            Node<T> lastnode = head;
            while (i<size){
                lastnode = lastnode.next;
                i++;
            }
            //设置新创建节点的前一个指向
            newnode.prenode=lastnode;
            //设置新创建节点的后一个指向
            newnode.next = lastnode.next;
            //设置尾结点的前指向
            lastnode.next.prenode = newnode;
            //追加新节点到最后一个节点上
            lastnode.next = newnode;
            size++;
        }
        //在正确的索引下添加一个元素
        public void preadd(int index,T value){
            if(index==size){
                preadd(value);
            }else {
                checkIndex(index);
                int i =0;
                Node<T> newnode = new Node<>(value);
                Node<T> indexnode = head;
                while (i<index){
                    indexnode = indexnode.next;
                    i++;
                }
                newnode.prenode = indexnode;
                newnode.next = indexnode.next;
                indexnode.next.prenode = newnode;
                indexnode.next = newnode;
                size++;
            }
        }
        //删除指定索引的元素
        public void remove(int index){
            checkIndex(index);
            int i = 0;
            Node<T> removenode = head;
            while(i<=index){
                removenode = removenode.next;
                i++;
            }
           removenode.prenode.next = removenode.next;
            removenode.next.prenode = removenode.prenode;
            size--;
        }
        //修改指定索引节点的值
        public void set(int index,T value){
            checkIndex(index);
            int i =0;
            Node<T> setNode = head;
            while (i<=index){
                setNode = setNode.next;
                i++;
            }
            setNode.value = value;
        }
        //删除值为value的节点
        public void remove(T value){
            int i =0;
            Node<T> removenode = head;
            int flag = 0;
            while (i<size){
                removenode = removenode.next;
                if(removenode.value.equals(value)){
                    remove(i);
                    System.out.println("成功删除值为"+value+"的数据");
                    //每次成功删除之后,后面的节点位置前移,判断的依旧是根据节点的next,但是删除的是i索引的值,若不进行减1,则会误删元素
                    i--;
                    flag++;
                }
                i++;
            }
            if(flag==0){
                System.out.println("未查找到要删除的数据");
            }
        }
        public void show (){
            Node<T> shownode = head;
            for (int i =0;i<size;i++){
                shownode = shownode.next;
                System.out.print(shownode.value+" ");
            }
            System.out.println();
        }
        public void show1 (){
            Node<T> shownode = end;
            for (int i =0;i<size;i++){
                shownode = shownode.prenode;
                System.out.print(shownode.value+" ");
            }
            System.out.println();
        }
        public void checkIndex(int index){
            if (index<0||index>=size){
                throw new IndexOutOfBoundsException("下标越界"+index);
            }
        }

    }

    public static void main(String[] args) {
        DoubleLinked<Integer> link1 = new DoubleLinked<Integer>();
        link1.preadd(4);
        link1.preadd(10);
        link1.preadd(6);
        link1.preadd(2,7);
        link1.preadd(3,9);
        link1.set(2,10);
        //link1.remove(1);

        link1.show();
        link1.show1();
        link1.remove((Integer) 10);
        link1.show1();
    }

}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值