JAVA数据结构之双链表

什么是双向链表

它的组成只是比单链表多了一些指
向前一个节点的前继节点,那么就
是我们对一个节点可以进行两个方
向的操作既前和后其它与单链表一
样。

双向链表的优缺点

优点:
在我们学习单链表的时候还记得我
们是怎么进行节点的删除的么?删
除节点的原理是通过节点指引 (引
用)的变化来进行删除节点, 在单
链表中我们总是需要找到要删除节
点的前继节点而在双向链表我们只
需要找到要删除的节点因为它含有
前继指引(引用)我们就减少寻找前
继节点的步骤。

缺点:
在我们添加节点的时候需要添加前
继节点增加了内存空间。

节点类:

public class DNode {
    private int data;
    DNode previous;
    DNode next;

    public DNode(int data,DNode previous,DNode next){
        this.data = data;
        this.previous = previous;
        this.next = next;
    }

    public int getData(){
        return this.data;
    }

}

下面我们来看双链表的一些基本操
作,为了方便解释这下方法其实都
在DList类里面但是在这里我为了
方便解释分开了

1.默认在链表尾部插入节点

public class DList {    
    //默认在链表尾部插入节点
    public void insertDNode(int val){
        DNode newNode = new DNode(val,null,null);
        if(head == null){
            head = newNode;
        }else{
            //寻找尾节点
            DNode temp = head;
            while(temp.next != null){
                temp = temp.next;
            }

            //将temp的后继指引指向newNode;
            temp.next = newNode; 

            //将newNode的前继指针指向temp;
            newNode.previous = temp; 

           //因为是双向链表索引必须将前继,后继指引设置好才算完整的节点插入
        }
    }
}

2.指定位置插入节点

//ps:这里的插入是前插入 节点插入位置为5,节点插入后5位置上的是新节点.
public void insertDNode(int val,int position){
   DNode newNode = new DNode(val,null,null);
   if(head == null){
       head = newNode;
   }else{
       int size = this.Dlength();
       if(position < 1 || position > size + 1){
           System.out.println("位置不合法");
       }
       if(position == 1){
           newNode.next = head;
           head.previous = newNode;
           //这里是head更新
           head = newNode;
       }else{
           int count = 1;
           DNode fastNode = head;
           while( count < size - 1){
               fastNode = fastNode.next;
               count++;
           }
           DNode slowNode = fastNode.next;
           newNode.next = slowNode;
           //截至到目前基本跟单链表的插入基本都一样,如果还不理解可以去看看单链表的那一篇
           //解释一下这里为什么需要判断如果slowNode 既是需要删除节点的后继节点不是NULL那么需要设置前继节点
           //如果不理解就可以画一下双链表的结构图 感觉链表相关的内容画一下结构图基本都可以掌握理解
           if(slowNode != null){
               slowNode.previous = newNode;
           }

           fastNode.next = newNode;//将newNode设为fastNode的后继节点
           newNode.previous = fastNode; //将fastNode设为newNode的前继节点

       }
   }
}

3.删除节点

 public void deleteDNode(int position){
        if(head == null){
            System.out.println("没有什么删除的!!!");
        }else{
            int size = Dlength();
            if(position < 1 || position > size + 1){
                System.out.println("The position can not use");
            }
            if(position == 1){
                head = head.next;
                head.previous = null;
            }else{
                  int count = 1;
                  DNode  fastNode = head;
                  //找到删除之前的前继节点
                  while( count < position - 1){
                      fastNode = fastNode.next;
                      count++;
                  }
                  //删除位置节点
                  DNode slowNode = fastNode.next; 
                  //删除位置的后继节点
                  DNode curNode = slowNode.next; 
                  //变动后继节点next
                  fastNode.next = curNode;
                  //判断是否需要前继节点  只要不是NULL都需要设置前继节点
                  if(curNode != null)  
                      curNode.previous = fastNode;
                  curNode = null;

            }
        }
    }

4.根据数据删除节点

//这个删除步骤不给出了,你能自己看懂么?
 public void deleteNodeByValue(int val){
        if(head == null){
            System.out.println("都没有!你删什么???");
        }else{
            DNode temp = head;
            while(temp.getData() != val){
                temp = temp.next;
            }
            DNode before = temp.previous;
            DNode after = temp.next;
            if(after != null){
                after.previous = before;
            }
            before.next = after;
        }
    }

5.遍历链表,链表长度

//遍历输出链表
    public void printALL(){
        DNode temp = head;
        while(temp != null){
            System.out.print(temp.getData()+" "); 
            temp = temp.next;
        }
        System.out.println();
    }

    //链表长度
    public int Dlength(){
        DNode temp = head;
        int le = 0;
        while(temp != null){
            le++;
            temp = temp.next;
        }
        return le;
    }

测试类:

public class TestDNode {

    public static void main(String[] args) {
        DList list = new DList();
        list.insertDNode(5);
        list.insertDNode(51);
        list.insertDNode(55);
        list.insertDNode(25);
        list.insertDNode(53);
        list.printALL();
        list.insertDNode(2, 1);
        list.printALL();
        list.deleteDNode(3);
        list.printALL();
        list.insertDNode(66);
        list.printALL();
        list.deleteNodeByValue(53);
        list.printALL();

    }

}

输出结果:
5 51 55 25 53 
2 5 51 55 25 53 
2 5 55 25 53 
2 5 55 25 53 66 
2 5 55 25 66 

上面是双链表的一些基础操作等循
环链表基本操作出完后我打算再写
一篇关于链表的常见问题。我会一
直写这些的让刚接触链表的不要像
我一样很吃力。

嘻嘻~~看完能关注一下么??我的公众号欢迎你们

我的公众号:程序传送门

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值