使用 Java 的 DSA - 双向链表


双向链表基础知识

双链表是链表的一种变体,与单链表相比,双链表可以轻松地向前和向后两种方式进行导航。以下是理解双向链表概念的重要术语

  • 链接- 链表的每个链接都可以存储称为元素的数据。

  • Next - 链接列表的每个链接都包含一个指向下一个链接的链接,称为“Next”。

  • Prev - 链接列表的每个链接都包含一个指向称为 Prev 的上一个链接的链接。

  • LinkedList - LinkedList 包含指向名为 First 的第一个链接和名为 Last 的最后一个链接的连接链接。

双向链表表示

双向链表

根据上图所示,以下是需要考虑的要点。

  • 双向链表包含一个名为first 和last 的链接元素。

  • 每个链接携带一个数据字段和一个接下来调用的链接字段。

  • 每个链接都使用其下一个链接与其下一个链接进行链接。

  • 每个链接都使用其上一个链接与其前一个链接进行链接。

  • Last Link 带有一个为 null 的 Link 来标记列表的结尾。

基本操作

以下是列表支持的基本操作。

  • 插入- 在列表的开头添加一个元素。

  • 删除- 删除列表开头的元素。

  • Insert Last - 在列表末尾添加一个元素。

  • 删除最后一个- 从列表末尾删除一个元素。

  • Insert After - 在列表的项目之后添加一个元素。

  • 删除- 使用 key 从列表中删除一个元素。

  • 向前显示- 以向前方式显示完整列表。

  • 向后显示- 以向后方式显示完整列表。

插入操作

以下代码演示了双向链表开头的插入操作。

//insert link at the first location
public void insertFirst(int key, int data){
   //create a link
   Link link = new Link(key,data);

   if(isEmpty()){
      //make it the last link
      last = link;
   }else {
      //update first prev link
      first.prev = link;
   }

   //point it to old first link
   link.next = first;
   //point first to new first link
   first = link;
}

删除操作

以下代码演示了双向链表开头的删除操作。

//delete link at the first location
public Link deleteFirst(){
   //save reference to first link
   Link tempLink = first;
   //if only one link
   if(first.next == null){
      last = null;
   }else {
      first.next.prev = null;
   }
   first = first.next;
   //return the deleted link
   return tempLink;
}

操作结束时插入

以下代码演示了双向链表中最后位置的插入操作。

//insert link at the last location
public void insertLast(int key, int data){
   //create a link
   Link link = new Link(key,data);

   if(isEmpty()){
      //make it the last link
      last = link;
   }else {
      //make link a new last link
      last.next = link;     
      //mark old last node as prev of new link
      link.prev = last;
   }

   //point last to new last node
   last = link;
}

演示

链接.java

package com.tutorialspoint.list;

public class Link {
   public int key;
   public int data;
   public Link next;
   public Link prev;

   public Link(int key, int data){
      this.key = key;
      this.data = data;
   }

   public void display(){
      System.out.print("{"+key+","+data+"}");
   }
}

双链表.java

package com.tutorialspoint.list;

public class DoublyLinkedList {
   
   //this link always point to first Link 
   private Link first;
   //this link always point to last Link 
   private Link last;

   // create an empty linked list 
   public DoublyLinkedList(){
      first = null;
      last = null;
   }

   //is list empty
   public boolean isEmpty(){
      return first == null;
   }

   //insert link at the first location
   public void insertFirst(int key, int data){
      //create a link
      Link link = new Link(key,data);

      if(isEmpty()){
         //make it the last link
         last = link;
      }else {
         //update first prev link
         first.prev = link;
      }

      //point it to old first link
      link.next = first;
      //point first to new first link
      first = link;
   }

   //insert link at the last location
   public void insertLast(int key, int data){
      //create a link
      Link link = new Link(key,data);

      if(isEmpty()){
         //make it the last link
         last = link;
      }else {
         //make link a new last link
         last.next = link;     
         //mark old last node as prev of new link
         link.prev = last;
      }

      //point last to new last node
      last = link;
   }

   //delete link at the first location
   public Link deleteFirst(){
      //save reference to first link
      Link tempLink = first;
      //if only one link
      if(first.next == null){
         last = null;
      }else {
         first.next.prev = null;
      }
      first = first.next;
      //return the deleted link
      return tempLink;
   }

   //delete link at the last location
   public Link deleteLast(){
      //save reference to last link
      Link tempLink = last;
      //if only one link
      if(first.next == null){
         first = null;
      }else {
         last.prev.next = null;
      }
      last = last.prev;
      //return the deleted link
      return tempLink;
   }

   //display the list in from first to last
   public void displayForward(){
      //start from the beginning
      Link current = first;
      //navigate till the end of the list
      System.out.print("[ ");
      while(current != null){
         //print data
         current.display();
         //move to next item
         current = current.next;
         System.out.print(" ");
      }      
      System.out.print(" ]");
   }

   //display the list from last to first
   public void displayBackward(){
      //start from the last
      Link current = last;
      //navigate till the start of the list
      System.out.print("[ ");
      while(current != null){
         //print data
         current.display();
         //move to next item
         current = current.prev;
         System.out.print(" ");
      }
      System.out.print(" ]");
   }

   //delete a link with given key
   public Link delete(int key){
      //start from the first link
      Link current = first;      
      //if list is empty
      if(first == null){
         return null;
      }

      //navigate through list
      while(current.key != key){
      //if it is last node
      if(current.next == null){
            return null;
         }else{           
            //move to next link
            current = current.next;             
         }
      }

      //found a match, update the link
      if(current == first) {
         //change first to point to next link
            first = current.next;
         }else {
            //bypass the current link
            current.prev.next = current.next;
         }    

         if(current == last){
            //change last to point to prev link
            last = current.prev;
         }else {
            current.next.prev = current.prev;
         }
         return current;
      }

   public boolean insertAfter(int key, int newKey, int data){
      //start from the first link
      Link current = first;      
      //if list is empty
      if(first == null){
         return false;
      }

      //navigate through list
      while(current.key != key){
         //if it is last node
         if(current.next == null){
            return false;
         }else{           
            //move to next link
            current = current.next;             
         }
      }

      Link newLink = new Link(newKey,data); 
      if(current==last) {
         newLink.next = null; 
         last = newLink; 
      }
      else {
         newLink.next = current.next;         
         current.next.prev = newLink;
      }
      newLink.prev = current; 
      current.next = newLink; 
      return true; 
   }
}

DoubleLinkedListDemo.java

package com.tutorialspoint.list;

public class DoublyLinkedListDemo {
    public static void main(String args[]){
        DoublyLinkedList list = new DoublyLinkedList();
        
        list.insertFirst(1, 10);
        list.insertFirst(2, 20);
        list.insertFirst(3, 30);
        
        list.insertLast(4, 1);
        list.insertLast(5, 40);
        list.insertLast(6, 56);
       
        System.out.print("\nList (First to Last): ");  
        list.displayForward();
        System.out.println("");
        System.out.print("\nList (Last to first): "); 
        list.displayBackward();
        
        System.out.print("\nList , after deleting first record: ");
        list.deleteFirst();        
        list.displayForward();
        
        System.out.print("\nList , after deleting last record: ");  
        list.deleteLast();
        list.displayForward();
        
        System.out.print("\nList , insert after key(4) : ");  
        list.insertAfter(4,7, 13);
        list.displayForward();
        
        System.out.print("\nList  , after delete key(4) : ");  
        list.delete(4);
        list.displayForward();
        
    }
}

如果我们编译并运行上面的程序,那么它将产生以下结果 -

List (First to Last): [ {3,30} {2,20} {1,10} {4,1} {5,40} {6,56}  ]

List (Last to first): [ {6,56} {5,40} {4,1} {1,10} {2,20} {3,30}  ]
List (First to Last) after deleting first record: [ {2,20} {1,10} {4,1} {5,40} {6,56}  ]
List  (First to Last) after deleting last record: [ {2,20} {1,10} {4,1} {5,40}  ]
List  (First to Last) insert after key(4) : [ {2,20} {1,10} {4,1} {7,13} {5,40}  ]
List  (First to Last) after delete key(4) : [ {2,20} {1,10} {7,13} {5,40}  ]