LinkedList is a linear data structure which allows to insert and remove elements at the front and rear in constant time.

LinkedLists are typically of two types,

- Single LinkedList

Each node has a reference to the next node. - Doubly LinkedList

Each node has a reference to previous and next nodes.

Doubly Linked Lists are used extensively in various computer science domains like caching, binary trees etc.

###### Node Structure

A Single Linkedlist typically has a node reference to the next node and a value, on the other hand the doubly linked list has two references, previous and next, pointing to different nodes.

```
class DNode{
DNode prev, next;
T val;
}
```

###### List Operations

The doubly linked list allows typical operations like adding or removing elements to the lists, search ane element in the list.

###### Implementation

```
package src.DSFullImplementations;
/*
* Author: Venkatesh Thallam
*
*/
public class DoubleLinkedListImpl {
/*
* Node definition with two pointers
*/
class DNode {
DNode prev, next;
int val;
DNode(int val) {
this.val = val;
prev = next = null;
}
}
/*
* Head points to the first element of the list and tail to the last
*/
DNode head, tail;
DoubleLinkedListImpl() {
this.head = this.tail = null;
}
public static void main(String[] args) {
DoubleLinkedListImpl list = new DoubleLinkedListImpl();
list.add(10, null);
list.add(20, 10);
list.add(30, 10);
list.add(40, 30);
list.print();
System.out.println("List size is " + list.size());
list.remove(30);
list.print();
list.remove(20);
list.print();
}
/*
* Adds an element after certain element. If ele is null, it inserts at the
* front
*/
public void add(int val, Integer ele) {
/*
* If target node is head
*/
if (head == null) {
head = tail = new DNode(val);
} else if (head.val == ele || ele == null) {
DNode temp = new DNode(val);
temp.next = head;
head.prev = temp;
head = temp;
}
/*
* If target node is tail
*/
else if (tail.val == ele) {
DNode newnode = new DNode(val);
tail.next = newnode;
newnode.prev = tail;
tail = newnode;
} else {
DNode newnode = new DNode(val);
DNode temp = head;
while (temp.next != null && temp.val != ele) {
temp = temp.next;
}
newnode.next = temp.next;
newnode.prev = temp;
temp.next = newnode;
}
}
/*
* Removes the specified element
*/
public void remove(int ele) {
/*
* If target node is head
*/
if (head.val == ele) {
head = head.next;
head.prev = null;
}
/*
* If target node is tail
*/
else if (tail.val == ele) {
tail = tail.prev;
tail.next = null;
} else {
DNode temp = head;
while (temp.next != null && temp.next.val != ele) {
temp = temp.next;
}
if (temp != null) {
temp.next = temp.next.next;
temp.next.prev = temp;
}
}
}
/*
* Checks whether a certain element is true
*/
public boolean search(int ele) {
DNode temp = head;
while (temp != null) {
if (temp.val == ele) {
return true;
}
temp = temp.next;
}
return false;
}
/*
* Returns the number of elements in the linked list.
*/
public int size() {
DNode temp = head;
int count = 0;
while (temp != null) {
count++;
temp = temp.next;
}
return count;
}
/*
* Prints the elements in the list
*/
public void print() {
DNode temp = head;
while (temp != null) {
System.out.print(temp.val + " ");
temp = temp.next;
}
System.out.println();
}
}
```

###### Time Complexity

The time complexity is similar to that of single linkedlists.