Advantages of two-way linked list compared with one-way linked list:
1. When the one-way linked list needs to operate on the tail of the list, it needs to get the tail nodes through traversal, which is a waste of time
2. For programs that need to use the deleteFromTail() and addToTail() methods frequently, the program efficiency will be very low
3. The bi-directional linked list stores the nodes in front of each node. When the tail is operated, it is very convenient to obtain the node information of the tail, to operate the tail, and to greatly improve the program efficiency
4. However, double linked list stores more references of an object than single linked list, which leads to higher space complexity
Here is the Java code:
package com.DoublyLinkedList; //DNode Class public class DoublyLinkedList { Node head; //Chain header node reference Node tail; //Link end reference int length; //Length of linked list //Constructor public DoublyLinkedList(){ head = tail = null; length = 0; } //Judge whether the list is empty int isEmpty(){ return head == null?1:0; } //Determine whether the linked list contains a value int contains(int value){ //Traverse the linked list to find the value for (Node now=head; now!=null; now=now.next) if (now.value == value) return 1; return 0; } //Add node to chain header void addToHead(int value){ //If the list is empty, add it directly if (head == null) head = tail = new Node(value, null, null); else //Link list is not empty, add node, update head head = head.pre = new Node(value, null, head); length++; } //Add a node to the end of the list void addToTail(int value){ //If the list is empty, add it directly if (head == null) head = tail = new Node(value, null, null); //Link list is not empty, add node, update tail else{ tail = tail.next = new Node(value, tail, null); } length++; } //Add a node to the specified subscript void addNode(int value, int index){ //If the specified subscript is illegal, return directly if (index > length+1 || index <= 0) return ; //If the list is empty and the specified subscript is not 1, return directly if (head==null && index!=1) return ; //If the list is empty, you need to add a new node if (head==null && index==1){ head = tail = new Node(value, null, null); } //If the list is not empty, you need to add nodes in the header else if (index==1) head = head.pre = new Node(value, null, head); //Link list is not empty, add nodes to the list else { int cnt = 0; Node aheadOfAdd=head; //Find the previous node to join for(cnt=1; cnt+1<index; cnt++) aheadOfAdd = aheadOfAdd.next; //If a node is added after the tail, update the tail if (aheadOfAdd == tail) tail = tail.next = new Node(value, tail, null); //Otherwise, join directly else aheadOfAdd.next = aheadOfAdd.next.pre = new Node(value, aheadOfAdd, aheadOfAdd.next); } length++; } //Delete the first node of the linked list int deleteFromHead(){ Node deletedNode = null; //If the list is empty, return directly if (head == null) return -1; //If there is only one node in the linked list, delete the node and update the head and tail if (head == tail) deletedNode = head; //Delete normal else{ deletedNode = head; head = head.next; head.pre = null; } length--; return deletedNode.value; } //Delete the last node of the linked list int deleteFromTail(){ Node deletedNode = null; //If the list is empty, return directly if (head == null) return -1; //If there is only one node in the linked list, delete the node and update the head and tail if (head == tail){ deletedNode = head; head = tail = null; } //Other circumstances else{ deletedNode = tail; tail = tail.pre; tail.next = null; } length--; return deletedNode.value; } //Delete node according to given subscript int deleteNode(int index){ //If the given index is obviously illegal, return directly if (index<=0 || index>length) return -1; //Nodes to delete Node deletedNode = head; //If the list is empty, return directly if (head == null) return -1; //If there is only one element in the linked list and other elements need to be deleted, return directly if (head == tail && index != 1) return -1; //If there is only one element in the linked list and the element needs to be deleted, update the head and tail if (head == tail && index == 1){ deletedNode = head; head = tail = null; } //If the chain header node needs to be deleted else if(index == 1){ deletedNode = head; head = head.next; head.pre = null; } //If you need to delete the end node of the list else if(index == length){ deletedNode = tail; tail = tail.pre; tail.next = null; } //Other circumstances else{ int cnt; for(deletedNode=head,cnt=1; cnt<index; cnt++, deletedNode=deletedNode.next); deletedNode.pre.next = deletedNode.next; deletedNode.next.pre = deletedNode.pre; } length--; return deletedNode.value; } //Print list //Print from front to back and from back to front to ensure that the forward and backward pointers are completely correct void printSelf(){ System.out.print("DoublyLinkedList: ["); for (Node now=head; now!=null; now=now.next) System.out.print(now.value + " "); System.out.print("] Backside front: ["); for (Node now=tail; now!=null; now=now.pre) System.out.print(now.value + " "); System.out.print("]\n\t\t"); String str = String.format("Head: %d\t\ttail: %d\t\tLength: %d\n", head.value, tail.value, length); System.out.print(str); } //Test function static public void main(String[] argv) { DoublyLinkedList list = new DoublyLinkedList(); list.addToHead(100);list.printSelf(); list.addToHead(200);list.printSelf(); list.addToTail(1);list.printSelf(); list.addToTail(2);list.printSelf(); list.addToTail(3);list.printSelf(); list.deleteFromTail();list.printSelf(); list.deleteFromTail();list.printSelf(); list.addNode(10000, 1);list.printSelf(); System.out.print("\n\n"); //list.deleteNode(1);list.printSelf(); System.out.println("empty?:" + list.isEmpty()); System.out.println("123456?: " + list.contains(123456)); System.out.println("10000?: " + list.contains(10000)); } } //Two way linked list node class class Node{ int value; //Node data Node pre; //Reference to previous node Node next; //Reference to the next node //Constructor 1, most commonly used public Node(int aValue){ value = aValue; pre = null; next = null; } //Constructor 2 public Node(int aValue, Node aPre, Node aNext){ value = aValue; pre = aPre; next = aNext; } }