mirror of
https://github.com/TheAlgorithms/Java.git
synced 2025-07-24 13:10:13 +08:00
Formatted with Google Java Formatter
This commit is contained in:
@ -1,343 +1,307 @@
|
||||
package DataStructures.Lists;
|
||||
|
||||
/**
|
||||
* This class implements a DoublyLinkedList. This is done using the classes
|
||||
* LinkedList and Link.
|
||||
* <p>
|
||||
* A linked list is similar to an array, it holds values. However,
|
||||
* links in a linked list do not have indexes. With a linked list
|
||||
* you do not need to predetermine it's size as it grows and shrinks
|
||||
* as it is edited. This is an example of a double ended, doubly
|
||||
* linked list. Each link references the next link and the previous
|
||||
* one.
|
||||
* This class implements a DoublyLinkedList. This is done using the classes LinkedList and Link.
|
||||
*
|
||||
* <p>A linked list is similar to an array, it holds values. However, links in a linked list do not
|
||||
* have indexes. With a linked list you do not need to predetermine it's size as it grows and
|
||||
* shrinks as it is edited. This is an example of a double ended, doubly linked list. Each link
|
||||
* references the next link and the previous one.
|
||||
*
|
||||
* @author Unknown
|
||||
*/
|
||||
|
||||
public class DoublyLinkedList {
|
||||
/**
|
||||
* Head refers to the front of the list
|
||||
*/
|
||||
private Link head;
|
||||
/**
|
||||
* Tail refers to the back of the list
|
||||
*/
|
||||
private Link tail;
|
||||
/** Head refers to the front of the list */
|
||||
private Link head;
|
||||
/** Tail refers to the back of the list */
|
||||
private Link tail;
|
||||
|
||||
/**
|
||||
* Size refers to the number of elements present in the list
|
||||
*/
|
||||
private int size;
|
||||
/** Size refers to the number of elements present in the list */
|
||||
private int size;
|
||||
|
||||
/**
|
||||
* Default Constructor
|
||||
*/
|
||||
public DoublyLinkedList() {
|
||||
head = null;
|
||||
tail = null;
|
||||
size = 0;
|
||||
/** Default Constructor */
|
||||
public DoublyLinkedList() {
|
||||
head = null;
|
||||
tail = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a list containing the elements of the array
|
||||
*
|
||||
* @param array the array whose elements are to be placed into this list
|
||||
* @throws NullPointerException if the specified collection is null
|
||||
*/
|
||||
public DoublyLinkedList(int[] array) {
|
||||
if (array == null) throw new NullPointerException();
|
||||
for (int i : array) {
|
||||
insertTail(i);
|
||||
}
|
||||
size = array.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a list containing the elements of the array
|
||||
*
|
||||
* @param array the array whose elements are to be placed into this list
|
||||
* @throws NullPointerException if the specified collection is null
|
||||
*/
|
||||
public DoublyLinkedList(int[] array) {
|
||||
if (array == null) throw new NullPointerException();
|
||||
for (int i : array) {
|
||||
insertTail(i);
|
||||
}
|
||||
size = array.length;
|
||||
/**
|
||||
* Insert an element at the head
|
||||
*
|
||||
* @param x Element to be inserted
|
||||
*/
|
||||
public void insertHead(int x) {
|
||||
Link newLink = new Link(x); // Create a new link with a value attached to it
|
||||
if (isEmpty()) // Set the first element added to be the tail
|
||||
tail = newLink;
|
||||
else head.previous = newLink; // newLink <-- currenthead(head)
|
||||
newLink.next = head; // newLink <--> currenthead(head)
|
||||
head = newLink; // newLink(head) <--> oldhead
|
||||
++size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert an element at the tail
|
||||
*
|
||||
* @param x Element to be inserted
|
||||
*/
|
||||
public void insertTail(int x) {
|
||||
Link newLink = new Link(x);
|
||||
newLink.next = null; // currentTail(tail) newlink -->
|
||||
if (isEmpty()) { // Check if there are no elements in list then it adds first element
|
||||
tail = newLink;
|
||||
head = tail;
|
||||
} else {
|
||||
tail.next = newLink; // currentTail(tail) --> newLink -->
|
||||
newLink.previous = tail; // currentTail(tail) <--> newLink -->
|
||||
tail = newLink; // oldTail <--> newLink(tail) -->
|
||||
}
|
||||
++size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert an element at the head
|
||||
*
|
||||
* @param x Element to be inserted
|
||||
*/
|
||||
public void insertHead(int x) {
|
||||
Link newLink = new Link(x); // Create a new link with a value attached to it
|
||||
if (isEmpty()) // Set the first element added to be the tail
|
||||
tail = newLink;
|
||||
else
|
||||
head.previous = newLink; // newLink <-- currenthead(head)
|
||||
newLink.next = head; // newLink <--> currenthead(head)
|
||||
head = newLink; // newLink(head) <--> oldhead
|
||||
++size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert an element at the tail
|
||||
*
|
||||
* @param x Element to be inserted
|
||||
*/
|
||||
public void insertTail(int x) {
|
||||
/**
|
||||
* Insert an element at the index
|
||||
*
|
||||
* @param x Element to be inserted
|
||||
* @param index Index(from start) at which the element x to be inserted
|
||||
*/
|
||||
public void insertElementByIndex(int x, int index) {
|
||||
if (index > size) throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
|
||||
if (index == 0) {
|
||||
insertHead(x);
|
||||
} else {
|
||||
if (index == size) {
|
||||
insertTail(x);
|
||||
} else {
|
||||
Link newLink = new Link(x);
|
||||
newLink.next = null; // currentTail(tail) newlink -->
|
||||
if (isEmpty()) { // Check if there are no elements in list then it adds first element
|
||||
tail = newLink;
|
||||
head = tail;
|
||||
} else {
|
||||
tail.next = newLink; // currentTail(tail) --> newLink -->
|
||||
newLink.previous = tail; // currentTail(tail) <--> newLink -->
|
||||
tail = newLink; // oldTail <--> newLink(tail) -->
|
||||
Link previousLink = head; //
|
||||
for (int i = 1; i < index; i++) { // Loop to reach the index
|
||||
previousLink = previousLink.next;
|
||||
}
|
||||
++size;
|
||||
// previousLink is the Link at index - 1 from start
|
||||
previousLink.next.previous = newLink;
|
||||
newLink.next = previousLink.next;
|
||||
newLink.previous = previousLink;
|
||||
previousLink.next = newLink;
|
||||
}
|
||||
}
|
||||
++size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the element at the head
|
||||
*
|
||||
* @return The new head
|
||||
*/
|
||||
public Link deleteHead() {
|
||||
Link temp = head;
|
||||
head = head.next; // oldHead <--> 2ndElement(head)
|
||||
|
||||
if (head == null) {
|
||||
tail = null;
|
||||
} else {
|
||||
head.previous =
|
||||
null; // oldHead --> 2ndElement(head) nothing pointing at old head so will be removed
|
||||
}
|
||||
--size;
|
||||
return temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the element at the tail
|
||||
*
|
||||
* @return The new tail
|
||||
*/
|
||||
public Link deleteTail() {
|
||||
Link temp = tail;
|
||||
tail = tail.previous; // 2ndLast(tail) <--> oldTail --> null
|
||||
|
||||
if (tail == null) {
|
||||
head = null;
|
||||
} else {
|
||||
tail.next = null; // 2ndLast(tail) --> null
|
||||
}
|
||||
--size;
|
||||
return temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the element from somewhere in the list
|
||||
*
|
||||
* @param x element to be deleted
|
||||
* @return Link deleted
|
||||
*/
|
||||
public void delete(int x) {
|
||||
Link current = head;
|
||||
|
||||
while (current.value != x) { // Find the position to delete
|
||||
if (current != tail) {
|
||||
current = current.next;
|
||||
} else { // If we reach the tail and the element is still not found
|
||||
throw new RuntimeException("The element to be deleted does not exist!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert an element at the index
|
||||
*
|
||||
* @param x Element to be inserted
|
||||
* @param index Index(from start) at which the element x to be inserted
|
||||
*
|
||||
*/
|
||||
public void insertElementByIndex(int x,int index){
|
||||
if(index > size) throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
|
||||
if(index == 0){
|
||||
insertHead(x);
|
||||
}else{
|
||||
if(index == size){
|
||||
insertTail(x);
|
||||
}else{
|
||||
Link newLink = new Link(x);
|
||||
Link previousLink = head; //
|
||||
for(int i = 1; i < index; i++){ //Loop to reach the index
|
||||
previousLink = previousLink.next;
|
||||
}
|
||||
// previousLink is the Link at index - 1 from start
|
||||
previousLink.next.previous = newLink;
|
||||
newLink.next = previousLink.next;
|
||||
newLink.previous = previousLink;
|
||||
previousLink.next = newLink;
|
||||
}
|
||||
}
|
||||
++size;
|
||||
|
||||
if (current == head) deleteHead();
|
||||
else if (current == tail) deleteTail();
|
||||
else { // Before: 1 <--> 2(current) <--> 3
|
||||
current.previous.next = current.next; // 1 --> 3
|
||||
current.next.previous = current.previous; // 1 <--> 3
|
||||
}
|
||||
--size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the element at the head
|
||||
*
|
||||
* @return The new head
|
||||
*/
|
||||
public Link deleteHead() {
|
||||
Link temp = head;
|
||||
head = head.next; // oldHead <--> 2ndElement(head)
|
||||
/**
|
||||
* Inserts element and reorders
|
||||
*
|
||||
* @param x Element to be added
|
||||
*/
|
||||
public void insertOrdered(int x) {
|
||||
Link newLink = new Link(x);
|
||||
Link current = head;
|
||||
while (current != null && x > current.value) // Find the position to insert
|
||||
current = current.next;
|
||||
|
||||
if (head == null) {
|
||||
tail = null;
|
||||
} else {
|
||||
head.previous = null; // oldHead --> 2ndElement(head) nothing pointing at old head so will be removed
|
||||
}
|
||||
--size;
|
||||
return temp;
|
||||
if (current == head) insertHead(x);
|
||||
else if (current == null) insertTail(x);
|
||||
else { // Before: 1 <--> 2(current) <--> 3
|
||||
newLink.previous = current.previous; // 1 <-- newLink
|
||||
current.previous.next = newLink; // 1 <--> newLink
|
||||
newLink.next = current; // 1 <--> newLink --> 2(current) <--> 3
|
||||
current.previous = newLink; // 1 <--> newLink <--> 2(current) <--> 3
|
||||
}
|
||||
++size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the element at the tail
|
||||
*
|
||||
* @return The new tail
|
||||
*/
|
||||
public Link deleteTail() {
|
||||
Link temp = tail;
|
||||
tail = tail.previous; // 2ndLast(tail) <--> oldTail --> null
|
||||
|
||||
if (tail == null) {
|
||||
head = null;
|
||||
} else{
|
||||
tail.next = null; // 2ndLast(tail) --> null
|
||||
}
|
||||
--size;
|
||||
return temp;
|
||||
/**
|
||||
* Deletes the passed node from the current list
|
||||
*
|
||||
* @param z Element to be deleted
|
||||
*/
|
||||
public void deleteNode(Link z) {
|
||||
if (z.next == null) {
|
||||
deleteTail();
|
||||
} else if (z == head) {
|
||||
deleteHead();
|
||||
} else { // before <-- 1 <--> 2(z) <--> 3 -->
|
||||
z.previous.next = z.next; // 1 --> 3
|
||||
z.next.previous = z.previous; // 1 <--> 3
|
||||
}
|
||||
--size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the element from somewhere in the list
|
||||
*
|
||||
* @param x element to be deleted
|
||||
* @return Link deleted
|
||||
*/
|
||||
public void delete(int x) {
|
||||
Link current = head;
|
||||
|
||||
while (current.value != x) {// Find the position to delete
|
||||
if (current != tail) {
|
||||
current = current.next;
|
||||
} else {// If we reach the tail and the element is still not found
|
||||
throw new RuntimeException("The element to be deleted does not exist!");
|
||||
}
|
||||
}
|
||||
|
||||
if (current == head)
|
||||
deleteHead();
|
||||
|
||||
else if (current == tail)
|
||||
deleteTail();
|
||||
|
||||
else { // Before: 1 <--> 2(current) <--> 3
|
||||
current.previous.next = current.next; // 1 --> 3
|
||||
current.next.previous = current.previous; // 1 <--> 3
|
||||
}
|
||||
--size;
|
||||
public static void removeDuplicates(DoublyLinkedList l) {
|
||||
Link linkOne = l.head;
|
||||
while (linkOne.next != null) { // list is present
|
||||
Link linkTwo = linkOne.next; // second link for comparison
|
||||
while (linkTwo.next != null) {
|
||||
if (linkOne.value == linkTwo.value) // if there are duplicates values then
|
||||
l.delete(linkTwo.value); // delete the link
|
||||
linkTwo = linkTwo.next; // go to next link
|
||||
}
|
||||
linkOne = linkOne.next; // go to link link to iterate the whole list again
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts element and reorders
|
||||
*
|
||||
* @param x Element to be added
|
||||
*/
|
||||
public void insertOrdered(int x) {
|
||||
Link newLink = new Link(x);
|
||||
Link current = head;
|
||||
while (current != null && x > current.value) // Find the position to insert
|
||||
current = current.next;
|
||||
/** Clears List */
|
||||
public void clearList() {
|
||||
head = null;
|
||||
tail = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
if (current == head)
|
||||
insertHead(x);
|
||||
/**
|
||||
* Returns true if list is empty
|
||||
*
|
||||
* @return true if list is empty
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return (head == null);
|
||||
}
|
||||
|
||||
else if (current == null)
|
||||
insertTail(x);
|
||||
|
||||
else { // Before: 1 <--> 2(current) <--> 3
|
||||
newLink.previous = current.previous; // 1 <-- newLink
|
||||
current.previous.next = newLink; // 1 <--> newLink
|
||||
newLink.next = current; // 1 <--> newLink --> 2(current) <--> 3
|
||||
current.previous = newLink; // 1 <--> newLink <--> 2(current) <--> 3
|
||||
}
|
||||
++size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the passed node from the current list
|
||||
*
|
||||
* @param z Element to be deleted
|
||||
*/
|
||||
public void deleteNode(Link z) {
|
||||
if(z.next == null){
|
||||
deleteTail();
|
||||
} else if(z == head){
|
||||
deleteHead();
|
||||
} else{ //before <-- 1 <--> 2(z) <--> 3 -->
|
||||
z.previous.next = z.next; // 1 --> 3
|
||||
z.next.previous = z.previous; // 1 <--> 3
|
||||
}
|
||||
--size;
|
||||
}
|
||||
|
||||
public static void removeDuplicates(DoublyLinkedList l ) {
|
||||
Link linkOne = l.head ;
|
||||
while(linkOne.next != null) { // list is present
|
||||
Link linkTwo = linkOne.next; // second link for comparison
|
||||
while(linkTwo.next!= null) {
|
||||
if(linkOne.value == linkTwo.value) // if there are duplicates values then
|
||||
l.delete(linkTwo.value); // delete the link
|
||||
linkTwo = linkTwo.next ; // go to next link
|
||||
}
|
||||
linkOne = linkOne.next; // go to link link to iterate the whole list again
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears List
|
||||
*
|
||||
*/
|
||||
public void clearList(){
|
||||
head = null;
|
||||
tail = null;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if list is empty
|
||||
*
|
||||
* @return true if list is empty
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return (head == null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints contents of the list
|
||||
*/
|
||||
public void display() { // Prints contents of the list
|
||||
Link current = head;
|
||||
while (current != null) {
|
||||
current.displayLink();
|
||||
current = current.next;
|
||||
}
|
||||
System.out.println();
|
||||
/** Prints contents of the list */
|
||||
public void display() { // Prints contents of the list
|
||||
Link current = head;
|
||||
while (current != null) {
|
||||
current.displayLink();
|
||||
current = current.next;
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class is used to implement the nodes of the
|
||||
* linked list.
|
||||
* This class is used to implement the nodes of the linked list.
|
||||
*
|
||||
* @author Unknown
|
||||
*/
|
||||
class Link {
|
||||
/**
|
||||
* Value of node
|
||||
*/
|
||||
public int value;
|
||||
/**
|
||||
* This points to the link in front of the new link
|
||||
*/
|
||||
public Link next;
|
||||
/**
|
||||
* This points to the link behind the new link
|
||||
*/
|
||||
public Link previous;
|
||||
/** Value of node */
|
||||
public int value;
|
||||
/** This points to the link in front of the new link */
|
||||
public Link next;
|
||||
/** This points to the link behind the new link */
|
||||
public Link previous;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param value Value of node
|
||||
*/
|
||||
public Link(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param value Value of node
|
||||
*/
|
||||
public Link(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the node
|
||||
*/
|
||||
public void displayLink() {
|
||||
System.out.print(value + " ");
|
||||
}
|
||||
/** Displays the node */
|
||||
public void displayLink() {
|
||||
System.out.print(value + " ");
|
||||
}
|
||||
|
||||
/**
|
||||
* Main Method
|
||||
*
|
||||
* @param args Command line arguments
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
DoublyLinkedList myList = new DoublyLinkedList();
|
||||
myList.insertHead(13);
|
||||
myList.insertHead(7);
|
||||
myList.insertHead(10);
|
||||
myList.display(); // <-- 10(head) <--> 7 <--> 13(tail) -->
|
||||
/**
|
||||
* Main Method
|
||||
*
|
||||
* @param args Command line arguments
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
DoublyLinkedList myList = new DoublyLinkedList();
|
||||
myList.insertHead(13);
|
||||
myList.insertHead(7);
|
||||
myList.insertHead(10);
|
||||
myList.display(); // <-- 10(head) <--> 7 <--> 13(tail) -->
|
||||
|
||||
myList.insertTail(11);
|
||||
myList.display(); // <-- 10(head) <--> 7 <--> 13 <--> 11(tail) -->
|
||||
myList.insertTail(11);
|
||||
myList.display(); // <-- 10(head) <--> 7 <--> 13 <--> 11(tail) -->
|
||||
|
||||
myList.deleteTail();
|
||||
myList.display(); // <-- 10(head) <--> 7 <--> 13(tail) -->
|
||||
myList.deleteTail();
|
||||
myList.display(); // <-- 10(head) <--> 7 <--> 13(tail) -->
|
||||
|
||||
myList.delete(7);
|
||||
myList.display(); // <-- 10(head) <--> 13(tail) -->
|
||||
myList.delete(7);
|
||||
myList.display(); // <-- 10(head) <--> 13(tail) -->
|
||||
|
||||
myList.insertOrdered(23);
|
||||
myList.insertOrdered(67);
|
||||
myList.insertOrdered(3);
|
||||
myList.display(); // <-- 3(head) <--> 10 <--> 13 <--> 23 <--> 67(tail) -->
|
||||
myList.insertElementByIndex(5, 1);
|
||||
myList.display(); // <-- 3(head) <--> 5 <--> 10 <--> 13 <--> 23 <--> 67(tail) -->
|
||||
myList.clearList();
|
||||
myList.display();
|
||||
myList.insertHead(20);
|
||||
myList.display();
|
||||
}
|
||||
myList.insertOrdered(23);
|
||||
myList.insertOrdered(67);
|
||||
myList.insertOrdered(3);
|
||||
myList.display(); // <-- 3(head) <--> 10 <--> 13 <--> 23 <--> 67(tail) -->
|
||||
myList.insertElementByIndex(5, 1);
|
||||
myList.display(); // <-- 3(head) <--> 5 <--> 10 <--> 13 <--> 23 <--> 67(tail) -->
|
||||
myList.clearList();
|
||||
myList.display();
|
||||
myList.insertHead(20);
|
||||
myList.display();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user