Algorithm and data structure [Java]: bidirectional linked list

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;
	}
}

 

79 original articles published, 53 praised, 40000 visitors+
Private letter follow

Keywords: Java

Added by Yanayaya on Sun, 26 Jan 2020 16:45:03 +0200