CC-9 : Implement DoubleLinkedList.
Description:
Create and test a DoubleLinkedList implementation.
DoubleLinkedList
DoubleLinkedLists consist of list of nodes, where each node has a 2 links. The first link points to the previous node and the second link points to the next node in the DoubleLinkedList. The structure of a DoubleLinkedListNode is shown below. In the image as the first node is the only node in the list, the nextNode and previousNode links will point to null indicating there are no other nodes in the DoubleLinkedList. The nextNode variable of the node will point to the next node if there is a next node or else it will point to null (similarly previousNode will point to previous node, if any).
null <- 11 -> null
In the below image, node with data 23 is the first node the DoubleLinkedList so its previousNode link points to null. Similarly, node with data 11 is the last node the DoubleLinkedList so its nextNode link points to null.
null <- 23 <- -> 47 <- ->11 -> null
Below is the code for the DoubleLinkedListNode java class:
public class DoubleLinkedListNode implements Node {
private DoubleLinkedListNode nextNode=null;
private DoubleLinkedListNode previousNode=null;
private int nodeData=0;
public DoubleLinkedListNode getNextNode() {
return nextNode;
}
public void setNextNode(DoubleLinkedListNode nextNode) {
this.nextNode = nextNode;
}
public DoubleLinkedListNode getPreviousNode() {
return previousNode;
}
public void setPreviousNode(DoubleLinkedListNode previousNode) {
this.previousNode = previousNode;
}
public int getNodeData() {
return nodeData;
}
public void setNodeData(int nodeData) {
this.nodeData = nodeData;
}
}
Besides DoubleLinkListNode class shown above we also need a class named DoubleLinkedList that contains a reference to the firstNode of the DoubleLinkedList and also contains all the code to add/delete/traverse/access nodes of the DoubleLinkedList.
(partial code snapshot of the DoubleLinkedList is given below):
public class DoubleLinkedList {
private DoubleLinkedListNode firstNode=null;
public DoubleLinkedListNode getFirstNode() {
...
}
public void setFirstNode(DoubleLinkedListNode firstNode) {
...
}
public DoubleLinkedListNode getLastNode() {
...
}
public boolean addLast(int data){
...
}
...
...
...
}
Addition of node to end of DoubleLinkedList
Pseudocode:
| To handle addition of a newNode to end of a DoubleLinkedList, we need to handle 2 cases:
|
| If the DoubleLinkedList is empty, add the newNode as the firstNode of the SingleLinkedList.
|
| If the DoubleLinkedList already has nodes:
Find the current last node of the DoubleLinkedList and add the newNode as the nextNode of this last node.
Set prevNode of newNode to current last node.
|
Code:
public boolean addLast(int data){
DoubleLinkedListNode node=new DoubleLinkedListNode();
node.setNodeData(data);
if (firstNode==null) {
firstNode=node;
node.setNextNode(null);
node.setPreviousNode(null);
return true;
}
else {
DoubleLinkedListNode currentNode=firstNode;
while (currentNode.getNextNode()!=null) {currentNode=currentNode.getNextNode();}
node.setPreviousNode(currentNode);
currentNode.setNextNode(node);
node.setNextNode(null);
return true;
}
}
Addition of node to start of SingleLinkedList.
Pseudocode:
| To handle addition of newNode to start of a DoubleLinkedList, we need to handle 2 cases:
|
| If the DoubleLinkedList is empty, add newNode as the firstNode of the DoubleLinkedList.
|
| If the DoubleLinkedList already has nodes:
Set nextNode variable of the newNode to current firstNode of the DoubleLinkedList.
Set prevNode variable of the current firstNode to newNode.
Set newNode as the firstNode of the DoubleLinkedList.
|
Code:
public boolean addFirst(int data){
DoubleLinkedListNode node=new DoubleLinkedListNode();
node.setNodeData(data);
if (firstNode==null) {
firstNode=node;
node.setNextNode(null);
node.setPreviousNode(null);
return true;
}else {
node.setNextNode(firstNode);
firstNode.setPreviousNode(node);
firstNode=node;
node.setPreviousNode(null);
return true;
}
}
Addition of node to particular position in DoubleLinkedList.
Pseudocode:
| To handle addition of a newNode to index pos of a DoubleLinkedList, we need to handle 3 cases:
|
| If pos is 0 add newNode to start of DoubleLinkedList.
|
| If pos is equal to number of nodes in the DoubleLinkedList, then add new node to end of the DoubleLinkedList.
|
| If pos is an intermediate index:
Identify the node oldPrevNode at position pos-1,and identify oldNextNode at position pos.
Set nextNode of newNode to oldNextNode.
Set nextNode of oldPrevNode to newNode.
Set prevNode of newNode to oldPrevNode.
Set prevNode of oldNextNode to newNode.
|
Code:
public boolean add(int data, int pos){
int size=getSize();
if ((pos<0) || (pos > size)) { return false;}
if (pos==0) {
addFirst(data);
return true;
}
if (pos==size) {
addLast(data);
return true;
}
DoubleLinkedListNode node=new DoubleLinkedListNode();
node.setNodeData(data);
DoubleLinkedListNode currentNode=firstNode;
DoubleLinkedListNode prevNode=null;
int idx=0;
while (currentNode !=null) {
if ((idx==pos)){
node.setNextNode(prevNode.getNextNode());
prevNode.setNextNode(node);
//setup previous node linkages
node.getNextNode().setPreviousNode(node);
node.setPreviousNode(prevNode);
return true;
}
prevNode=currentNode;
currentNode=currentNode.getNextNode();
idx++;
}
return false;
}
Deletion of first node of DoubleLinkedList.
Pseudocode:
| To handle deletion of firstNode of DoubleLinkedList, we need to handle 2 cases:
|
| If the DoubleLinkedList has only one node, the set firstNode variable of DoubleLinkedList null.
|
| If the DoubleLinkedList already has more than 1 nodes:
Set prevNode of current firstNode to newNode.
Set firstNode of DoubleLinkedList to firstNode.nextNode.
|
Code:
public boolean removeFirst() {
if (firstNode == null) { return false; }
if (firstNode.getNextNode()==null) {
firstNode=null;
return true;
}
firstNode=firstNode.getNextNode();
firstNode.setPreviousNode(null);
return true;
}
Deletion of last node of DoubleLinkedList.
Pseudocode:
| To handle deletion of last node of DoubleLinkedList, we need to handle 2 cases:
|
| If the DouleLinkedList has only one node, the set firstNode variable of DoubleLinkedList null.
|
| If the DoubleLinkedList already has more than 1 nodes:
Find the second last node of the DoubleLinkedList and store its reference in prevNode.
Set prevNode.nextNode to null.
|
Code:
public boolean removeLast() {
if (firstNode == null) { return false; }
DoubleLinkedListNode currentNode=firstNode;
DoubleLinkedListNode prevNode=null;
while (currentNode !=null) {
if (currentNode.getNextNode()==null) {
if (prevNode==null) {
firstNode=null;
return true;
}
prevNode.setNextNode(null);
currentNode.setPreviousNode(null);
return true;
}
prevNode=currentNode;
currentNode=currentNode.getNextNode();
}
return false;
}
Deletion of intermediate node of DoubleLinkedList.
Pseudocode:
| To handle deletion of a node from index pos of a DoubleLinkedList, we need to handle 3 cases:
|
| If pos is 0, remove the firstNode of DoubleLinkedList.
|
| If pos is equal to number of nodes in the DoubleLinkedList, then remove the last node of the DoubleLinkedList.
|
| If pos is an intermediate index:
Identify the node prevNode at position pos-1.
Identify the node currentNode at position pos.
Set prevNode.nextNode to currentNode.nextNode.
Set currentNode.prevNode to prevNode.
|
Code:
public boolean removeAtPos(int pos){
DoubleLinkedListNode currentNode=firstNode;
DoubleLinkedListNode prevNode=null;
int idx=0;
while (currentNode !=null) {
if (idx==pos) {
if (prevNode==null) {
removeFirst();
return true;
}
if (currentNode.getNextNode()==null) {
removeLast();
return true;
}
prevNode.setNextNode(currentNode.getNextNode());
return true;
}
prevNode=currentNode;
currentNode=currentNode.getNextNode();
idx++;
}
return false;
}
Accessing a node at a particular index in the DoubleLinkedList.
Pseudocode:
| To access a node at particular index, use the nextNode link to traverse through the DoubleLinkedList till the required node is reached.
|
Code:
public int get(int idx) {
DoubleLinkedListNode currentNode=firstNode;
int currIdx=0;
while (currentNode !=null) {
if (currIdx==idx) {return currentNode.getNodeData();}
currentNode=currentNode.getNextNode();
currIdx++;
}
return Integer.MIN_VALUE;
}
Accessing/ printing the nodes of the DoubleLinkedList.
Pseudocode:
| The nextNode link of each node can be used to traverse the nodes of the DoubleLinkedList.
|
Code:
public void traverseForward() {
DoubleLinkedListNode currentNode=firstNode;
while (currentNode !=null) {
System.out.println(currentNode.getNodeData());
currentNode=currentNode.getNextNode();
}
}
Click here to download and run code and test cases !
Below fully running code can be copied and run on Eclipse or other Java IDEs. Refer the classname in code below. If the class name below is "A", save the code below to a file named A.java before running it.
Be sure to try your own test cases to enhance your understanding !
You can also tweak the code to optimize or add enhancements and custom features.
public class DoubleLinkedList {
private DoubleLinkedListNode firstNode=null;
public DoubleLinkedListNode getFirstNode() {
return firstNode;
}
public void setFirstNode(DoubleLinkedListNode firstNode) {
this.firstNode = firstNode;
}
public DoubleLinkedListNode getLastNode() {
DoubleLinkedListNode currentNode=firstNode;
DoubleLinkedListNode prevNode=null;
while (currentNode !=null) {
prevNode=currentNode;
currentNode=currentNode.getNextNode();
}
return prevNode;
}
public boolean addLast(int data){
DoubleLinkedListNode node=new DoubleLinkedListNode();
node.setNodeData(data);
if (firstNode==null) {
firstNode=node;
node.setNextNode(null);
node.setPreviousNode(null);
return true;
}
else {
DoubleLinkedListNode currentNode=firstNode;
while (currentNode.getNextNode()!=null) {currentNode=currentNode.getNextNode();}
node.setPreviousNode(currentNode);
currentNode.setNextNode(node);
node.setNextNode(null);
return true;
}
}
public boolean addFirst(int data){
DoubleLinkedListNode node=new DoubleLinkedListNode();
node.setNodeData(data);
if (firstNode==null) {
firstNode=node;
node.setNextNode(null);
node.setPreviousNode(null);
return true;
}else {
node.setNextNode(firstNode);
firstNode.setPreviousNode(node);
firstNode=node;
node.setPreviousNode(null);
return true;
}
}
public boolean add(int data, int pos){
int size=getSize();
if ((pos<0) || (pos > size)) { return false;}
if (pos==0) {
addFirst(data);
return true;
}
if (pos==size) {
addLast(data);
return true;
}
DoubleLinkedListNode node=new DoubleLinkedListNode();
node.setNodeData(data);
DoubleLinkedListNode currentNode=firstNode;
DoubleLinkedListNode prevNode=null;
int idx=0;
while (currentNode !=null) {
if ((idx==pos)){
node.setNextNode(prevNode.getNextNode());
prevNode.setNextNode(node);
//setup previous node linkages
node.getNextNode().setPreviousNode(node);
node.setPreviousNode(prevNode);
return true;
}
prevNode=currentNode;
currentNode=currentNode.getNextNode();
idx++;
}
return false;
}
public int getSize() {
DoubleLinkedListNode currentNode=firstNode;
int idx=0;
while (currentNode !=null) {
currentNode=currentNode.getNextNode();
idx++;
}
return idx;
}
public boolean removeFirst() {
if (firstNode == null) { return false; }
if (firstNode.getNextNode()==null) {
firstNode=null;
return true;
}
firstNode=firstNode.getNextNode();
firstNode.setPreviousNode(null);
return true;
}
public boolean removeLast() {
if (firstNode == null) { return false; }
DoubleLinkedListNode currentNode=firstNode;
DoubleLinkedListNode prevNode=null;
while (currentNode !=null) {
if (currentNode.getNextNode()==null) {
if (prevNode==null) {
firstNode=null;
return true;
}
prevNode.setNextNode(null);
currentNode.setPreviousNode(null);
return true;
}
prevNode=currentNode;
currentNode=currentNode.getNextNode();
}
return false;
}
public boolean remove(int data){
DoubleLinkedListNode currentNode=firstNode;
DoubleLinkedListNode prevNode=null;
while (currentNode !=null) {
if (currentNode.getNodeData() == data) {
if (prevNode==null) {
removeFirst();
return true;
}
if (currentNode.getNextNode()==null) {
removeLast();
return true;
}
prevNode.setNextNode(currentNode.getNextNode());
prevNode.getNextNode().setPreviousNode(prevNode);
return true;
}
prevNode=currentNode;
currentNode=currentNode.getNextNode();
}
return false;
}
public boolean removeAtPos(int pos){
DoubleLinkedListNode currentNode=firstNode;
DoubleLinkedListNode prevNode=null;
int idx=0;
while (currentNode !=null) {
if (idx==pos) {
if (prevNode==null) {
removeFirst();
return true;
}
if (currentNode.getNextNode()==null) {
removeLast();
return true;
}
prevNode.setNextNode(currentNode.getNextNode());
return true;
}
prevNode=currentNode;
currentNode=currentNode.getNextNode();
idx++;
}
return false;
}
public int get(int idx) {
DoubleLinkedListNode currentNode=firstNode;
int currIdx=0;
while (currentNode !=null) {
if (currIdx==idx) {return currentNode.getNodeData();}
currentNode=currentNode.getNextNode();
currIdx++;
}
return Integer.MIN_VALUE;
}
public void traverseForward() {
DoubleLinkedListNode currentNode=firstNode;
while (currentNode !=null) {
System.out.println(currentNode.getNodeData());
currentNode=currentNode.getNextNode();
}
}
// print DoubleLinkList forward direction
public void printDoubleLinkListForwardDirection() throws Exception {
// Case 1: The Linked list is empty !!
if (firstNode == null) { System.out.println("Double Linked list empty"); return; }
// Case 2: Print Double LinkedList node by node (first to last)
DoubleLinkedListNode currentNode=firstNode;
System.out.println();
System.out.println("****************************************************************************");
System.out.print("DoubleLinkedList nodes (first node to last node): ");
do {
System.out.print(currentNode.getNodeData());
if (currentNode.getNextNode()!=null) System.out.print(" -> ");
currentNode=currentNode.getNextNode();
} while( currentNode != null);
System.out.println();
System.out.println("****************************************************************************");
System.out.println();
Thread.sleep(2000);
;
return;
}
// print DoubleLinkList backward direction
public void printDoubleLinkListBackwardDirection() throws Exception {
// Case 1: The Linked list is empty !!
if (firstNode == null) { System.out.println("Double Linked list empty"); return; }
// Case 2: Print Double LinkedList node by node (last to first)
// This while loop executes till we reach last node in the LinkedList
DoubleLinkedListNode currentNode=firstNode;
while (currentNode.getNextNode()!=null) {currentNode=currentNode.getNextNode();}
//currentNode is at end of LinkedList
System.out.println();
System.out.println("****************************************************************************");
System.out.print("DoubleLinkedList nodes (last node to first node): ");
do {
System.out.print(currentNode.getNodeData());
if (currentNode != firstNode) System.out.print(" -> ");
currentNode=currentNode.getPreviousNode();
} while( currentNode != null);
System.out.println();
System.out.println("****************************************************************************");
System.out.println();
Thread.sleep(2000);
;
return;
}
public static void main(String[] args) {
try {
DoubleLinkedList doubleLinkedList=new DoubleLinkedList();
System.out.print("Add First");
doubleLinkedList.addFirst(9);
doubleLinkedList.printDoubleLinkListForwardDirection();
doubleLinkedList.printDoubleLinkListBackwardDirection();
System.out.print("Add First");
doubleLinkedList.addFirst(5);
doubleLinkedList.printDoubleLinkListForwardDirection();
doubleLinkedList.printDoubleLinkListBackwardDirection();
System.out.print("Add First");
doubleLinkedList.addFirst(3);
doubleLinkedList.printDoubleLinkListForwardDirection();
doubleLinkedList.printDoubleLinkListBackwardDirection();
System.out.print("remove First");
doubleLinkedList.removeFirst();
doubleLinkedList.printDoubleLinkListForwardDirection();
doubleLinkedList.printDoubleLinkListBackwardDirection();
System.out.print("remove First");
doubleLinkedList.removeFirst();
doubleLinkedList.printDoubleLinkListForwardDirection();
doubleLinkedList.printDoubleLinkListBackwardDirection();
System.out.print("remove First");
doubleLinkedList.removeFirst();
doubleLinkedList.printDoubleLinkListForwardDirection();
doubleLinkedList.printDoubleLinkListBackwardDirection();
System.out.print("remove First");
doubleLinkedList.removeFirst();
doubleLinkedList.printDoubleLinkListForwardDirection();
doubleLinkedList.printDoubleLinkListBackwardDirection();
System.out.print("************************************************************");
System.out.print("Add Last");
doubleLinkedList.addLast(9);
doubleLinkedList.printDoubleLinkListForwardDirection();
doubleLinkedList.printDoubleLinkListBackwardDirection();
System.out.print("Add Last");
doubleLinkedList.addLast(5);
doubleLinkedList.printDoubleLinkListForwardDirection();
doubleLinkedList.printDoubleLinkListBackwardDirection();
System.out.print("Add Last");
doubleLinkedList.addLast(3);
doubleLinkedList.printDoubleLinkListForwardDirection();
doubleLinkedList.printDoubleLinkListBackwardDirection();
System.out.print("remove Last");
doubleLinkedList.removeLast();
doubleLinkedList.printDoubleLinkListForwardDirection();
doubleLinkedList.printDoubleLinkListBackwardDirection();
System.out.print("remove Last");
doubleLinkedList.removeLast();
doubleLinkedList.printDoubleLinkListForwardDirection();
doubleLinkedList.printDoubleLinkListBackwardDirection();
System.out.print("remove Last");
doubleLinkedList.removeLast();
doubleLinkedList.printDoubleLinkListForwardDirection();
doubleLinkedList.printDoubleLinkListBackwardDirection();
System.out.print("remove Last");
doubleLinkedList.removeLast();
doubleLinkedList.printDoubleLinkListForwardDirection();
doubleLinkedList.printDoubleLinkListBackwardDirection();
System.out.print("************************************************************");
System.out.print("Add First");
doubleLinkedList.addFirst(9);
doubleLinkedList.printDoubleLinkListForwardDirection();
doubleLinkedList.printDoubleLinkListBackwardDirection();
System.out.print("Add First");
doubleLinkedList.addFirst(5);
doubleLinkedList.printDoubleLinkListForwardDirection();
doubleLinkedList.printDoubleLinkListBackwardDirection();
System.out.print("Add First");
doubleLinkedList.addFirst(3);
doubleLinkedList.printDoubleLinkListForwardDirection();
doubleLinkedList.printDoubleLinkListBackwardDirection();
System.out.print("Add Last");
doubleLinkedList.addLast(12);
doubleLinkedList.printDoubleLinkListForwardDirection();
doubleLinkedList.printDoubleLinkListBackwardDirection();
System.out.print("Add Last");
doubleLinkedList.addLast(15);
doubleLinkedList.printDoubleLinkListForwardDirection();
doubleLinkedList.printDoubleLinkListBackwardDirection();
System.out.print("Add Last");
doubleLinkedList.addLast(23);
doubleLinkedList.printDoubleLinkListForwardDirection();
doubleLinkedList.printDoubleLinkListBackwardDirection();
System.out.println("**************SIZE : "+doubleLinkedList.getSize());
System.out.print("Remove 3");
doubleLinkedList.remove(3);
doubleLinkedList.printDoubleLinkListForwardDirection();
doubleLinkedList.printDoubleLinkListBackwardDirection();
System.out.print("Remove 15");
doubleLinkedList.remove(15);
doubleLinkedList.printDoubleLinkListForwardDirection();
doubleLinkedList.printDoubleLinkListBackwardDirection();
System.out.print("Remove 9");
doubleLinkedList.remove(9);
doubleLinkedList.printDoubleLinkListForwardDirection();
doubleLinkedList.printDoubleLinkListBackwardDirection();
System.out.print("Remove 23");
doubleLinkedList.remove(23);
doubleLinkedList.printDoubleLinkListForwardDirection();
doubleLinkedList.printDoubleLinkListBackwardDirection();
System.out.println("**************SIZE : "+doubleLinkedList.getSize());
System.out.print("Add 55 Pos 1");
doubleLinkedList.add(55,1);
doubleLinkedList.printDoubleLinkListForwardDirection();
doubleLinkedList.printDoubleLinkListBackwardDirection();
System.out.print("Add 77 Pos 1");
doubleLinkedList.add(77,1);
doubleLinkedList.printDoubleLinkListForwardDirection();
doubleLinkedList.printDoubleLinkListBackwardDirection();
System.out.print("Add 88 Pos 4");
doubleLinkedList.add(88,4);
doubleLinkedList.printDoubleLinkListForwardDirection();
doubleLinkedList.printDoubleLinkListBackwardDirection();
System.out.print("Add 99 Pos 0");
doubleLinkedList.add(99,0);
doubleLinkedList.printDoubleLinkListForwardDirection();
doubleLinkedList.printDoubleLinkListBackwardDirection();
System.out.println("ELEMENT AT IDX : 0 "+doubleLinkedList.get(0));
System.out.println("ELEMENT AT IDX : 6 "+doubleLinkedList.get(6));
System.out.println("ELEMENT AT IDX : 5 "+doubleLinkedList.get(5));
System.out.println("ELEMENT AT IDX : 2 "+doubleLinkedList.get(2));
System.out.println("TRAVERSE ***** ");
doubleLinkedList.traverseForward();
System.out.print("************************************************************");
doubleLinkedList.addFirst(77);
doubleLinkedList.printDoubleLinkListForwardDirection();
System.out.print("Remove 77");
//DoubleLinkedListRemoveDuplicates.doubleLinkedListRemoveDuplicates(doubleLinkedList);
doubleLinkedList.printDoubleLinkListForwardDirection();
doubleLinkedList.addFirst(88);
doubleLinkedList.addLast(88);
doubleLinkedList.printDoubleLinkListForwardDirection();
System.out.print("Remove 88");
//.doubleLinkedListRemoveDuplicates(doubleLinkedList);
doubleLinkedList.printDoubleLinkListForwardDirection();
System.out.print("************************************************************");
System.out.print("REVERSING");
//.doubleLinkedListReversal(doubleLinkedList);
doubleLinkedList.printDoubleLinkListForwardDirection();
System.out.print("REVERSING");
//DoubleLinkedListReversal.doubleLinkedListReversal(doubleLinkedList);
doubleLinkedList.printDoubleLinkListForwardDirection();
}catch (Exception exception) {
System.out.print("Exception: "+ exception);
}
}
public class DoubleLinkedListNode {
private DoubleLinkedListNode nextNode=null;
private DoubleLinkedListNode previousNode=null;
private int nodeData=0;
public DoubleLinkedListNode getNextNode() {
return nextNode;
}
public void setNextNode(DoubleLinkedListNode nextNode) {
this.nextNode = nextNode;
}
public DoubleLinkedListNode getPreviousNode() {
return previousNode;
}
public void setPreviousNode(DoubleLinkedListNode previousNode) {
this.previousNode = previousNode;
}
public int getNodeData() {
return nodeData;
}
public void setNodeData(int nodeData) {
this.nodeData = nodeData;
}
}
}