mirror of
https://github.com/TheAlgorithms/Java.git
synced 2025-07-07 09:45:04 +08:00
Refactor to remove code smells (#2982)
Co-authored-by: Rushi <rs397441@dal.ca>
This commit is contained in:
@ -12,7 +12,7 @@ import java.util.Scanner;
|
|||||||
*/
|
*/
|
||||||
public class HillCipher {
|
public class HillCipher {
|
||||||
|
|
||||||
static Scanner in = new Scanner(System.in);
|
static Scanner userInput = new Scanner(System.in);
|
||||||
|
|
||||||
/* Following function encrypts the message
|
/* Following function encrypts the message
|
||||||
*/
|
*/
|
||||||
@ -20,26 +20,23 @@ public class HillCipher {
|
|||||||
message = message.toUpperCase();
|
message = message.toUpperCase();
|
||||||
// Get key matrix
|
// Get key matrix
|
||||||
System.out.println("Enter key matrix size");
|
System.out.println("Enter key matrix size");
|
||||||
int n = in.nextInt();
|
int matrixSize = userInput.nextInt();
|
||||||
System.out.println("Enter Key/encryptionKey matrix ");
|
System.out.println("Enter Key/encryptionKey matrix ");
|
||||||
int keyMatrix[][] = new int[n][n];
|
int keyMatrix[][] = new int[matrixSize][matrixSize];
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < matrixSize; i++) {
|
||||||
for (int j = 0; j < n; j++) {
|
for (int j = 0; j < matrixSize; j++) {
|
||||||
keyMatrix[i][j] = in.nextInt();
|
keyMatrix[i][j] = userInput.nextInt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//check if det = 0
|
//check if det = 0
|
||||||
if (determinant(keyMatrix, n) % 26 == 0) {
|
validateDeterminant(keyMatrix,matrixSize);
|
||||||
System.out.println("Invalid key, as determinant = 0. Program Terminated");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int[][] messageVector = new int[n][1];
|
int[][] messageVector = new int[matrixSize][1];
|
||||||
String CipherText = "";
|
String CipherText = "";
|
||||||
int cipherMatrix[][] = new int[n][1];
|
int cipherMatrix[][] = new int[matrixSize][1];
|
||||||
int j = 0;
|
int j = 0;
|
||||||
while (j < message.length()) {
|
while (j < message.length()) {
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < matrixSize; i++) {
|
||||||
if (j >= message.length()) {
|
if (j >= message.length()) {
|
||||||
messageVector[i][0] = 23;
|
messageVector[i][0] = 23;
|
||||||
} else {
|
} else {
|
||||||
@ -49,16 +46,16 @@ public class HillCipher {
|
|||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
int x, i;
|
int x, i;
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < matrixSize; i++) {
|
||||||
cipherMatrix[i][0] = 0;
|
cipherMatrix[i][0] = 0;
|
||||||
|
|
||||||
for (x = 0; x < n; x++) {
|
for (x = 0; x < matrixSize; x++) {
|
||||||
cipherMatrix[i][0] += keyMatrix[i][x] * messageVector[x][0];
|
cipherMatrix[i][0] += keyMatrix[i][x] * messageVector[x][0];
|
||||||
}
|
}
|
||||||
System.out.println(cipherMatrix[i][0]);
|
System.out.println(cipherMatrix[i][0]);
|
||||||
cipherMatrix[i][0] = cipherMatrix[i][0] % 26;
|
cipherMatrix[i][0] = cipherMatrix[i][0] % 26;
|
||||||
}
|
}
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < matrixSize; i++) {
|
||||||
CipherText += (char) (cipherMatrix[i][0] + 65);
|
CipherText += (char) (cipherMatrix[i][0] + 65);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -70,19 +67,17 @@ public class HillCipher {
|
|||||||
message = message.toUpperCase();
|
message = message.toUpperCase();
|
||||||
// Get key matrix
|
// Get key matrix
|
||||||
System.out.println("Enter key matrix size");
|
System.out.println("Enter key matrix size");
|
||||||
int n = in.nextInt();
|
int n = userInput.nextInt();
|
||||||
System.out.println("Enter inverseKey/decryptionKey matrix ");
|
System.out.println("Enter inverseKey/decryptionKey matrix ");
|
||||||
int keyMatrix[][] = new int[n][n];
|
int keyMatrix[][] = new int[n][n];
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
for (int j = 0; j < n; j++) {
|
for (int j = 0; j < n; j++) {
|
||||||
keyMatrix[i][j] = in.nextInt();
|
keyMatrix[i][j] = userInput.nextInt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//check if det = 0
|
//check if det = 0
|
||||||
if (determinant(keyMatrix, n) % 26 == 0) {
|
validateDeterminant(keyMatrix,n);
|
||||||
System.out.println("Invalid key, as determinant = 0. Program Terminated");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//solving for the required plaintext message
|
//solving for the required plaintext message
|
||||||
int[][] messageVector = new int[n][1];
|
int[][] messageVector = new int[n][1];
|
||||||
String PlainText = "";
|
String PlainText = "";
|
||||||
@ -145,12 +140,12 @@ public class HillCipher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Function to implement Hill Cipher
|
// Function to implement Hill Cipher
|
||||||
static void hillcipher(String message) {
|
static void hillCipher(String message) {
|
||||||
message.toUpperCase();
|
message.toUpperCase();
|
||||||
System.out.println("What do you want to process from the message?");
|
System.out.println("What do you want to process from the message?");
|
||||||
System.out.println("Press 1: To Encrypt");
|
System.out.println("Press 1: To Encrypt");
|
||||||
System.out.println("Press 2: To Decrypt");
|
System.out.println("Press 2: To Decrypt");
|
||||||
short sc = in.nextShort();
|
short sc = userInput.nextShort();
|
||||||
if (sc == 1) {
|
if (sc == 1) {
|
||||||
encrypt(message);
|
encrypt(message);
|
||||||
} else if (sc == 2) {
|
} else if (sc == 2) {
|
||||||
@ -160,11 +155,18 @@ public class HillCipher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void validateDeterminant(int[][] keyMatrix, int n){
|
||||||
|
if (determinant(keyMatrix, n) % 26 == 0) {
|
||||||
|
System.out.println("Invalid key, as determinant = 0. Program Terminated");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Driver code
|
// Driver code
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
// Get the message to be encrypted
|
// Get the message to be encrypted
|
||||||
System.out.println("Enter message");
|
System.out.println("Enter message");
|
||||||
String message = in.nextLine();
|
String message = userInput.nextLine();
|
||||||
hillcipher(message);
|
hillCipher(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -18,11 +18,15 @@ public class DoublyLinkedList {
|
|||||||
/**
|
/**
|
||||||
* Head refers to the front of the list
|
* Head refers to the front of the list
|
||||||
*/
|
*/
|
||||||
private Link head;
|
protected Link head;
|
||||||
/**
|
/**
|
||||||
* Tail refers to the back of the list
|
* Tail refers to the back of the list
|
||||||
*/
|
*/
|
||||||
private Link tail;
|
private Link tail;
|
||||||
|
/**
|
||||||
|
* Link Operations to perform operations on nodes of the list
|
||||||
|
*/
|
||||||
|
private LinkOperations linkOperations;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Size refers to the number of elements present in the list
|
* Size refers to the number of elements present in the list
|
||||||
@ -49,19 +53,152 @@ public class DoublyLinkedList {
|
|||||||
throw new NullPointerException();
|
throw new NullPointerException();
|
||||||
}
|
}
|
||||||
for (int i : array) {
|
for (int i : array) {
|
||||||
insertTail(i);
|
linkOperations.insertTail(i,this);
|
||||||
}
|
}
|
||||||
size = array.length;
|
size = array.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 the contents of the list in reverse order
|
||||||
|
*/
|
||||||
|
public void displayBackwards() {
|
||||||
|
Link current = tail;
|
||||||
|
while (current != null) {
|
||||||
|
current.displayLink();
|
||||||
|
current = current.previous;
|
||||||
|
}
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param value Value of node
|
||||||
|
*/
|
||||||
|
public Link(int value) {
|
||||||
|
this.value = 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();
|
||||||
|
LinkOperations linkOperations = new LinkOperations();
|
||||||
|
linkOperations.insertHead(13,myList);
|
||||||
|
linkOperations.insertHead(7,myList);
|
||||||
|
linkOperations.insertHead(10,myList);
|
||||||
|
myList.display(); // <-- 10(head) <--> 7 <--> 13(tail) -->
|
||||||
|
myList.displayBackwards();
|
||||||
|
|
||||||
|
linkOperations.insertTail(11,myList);
|
||||||
|
myList.display(); // <-- 10(head) <--> 7 <--> 13 <--> 11(tail) -->
|
||||||
|
myList.displayBackwards();
|
||||||
|
|
||||||
|
linkOperations.deleteTail();
|
||||||
|
myList.display(); // <-- 10(head) <--> 7 <--> 13(tail) -->
|
||||||
|
myList.displayBackwards();
|
||||||
|
|
||||||
|
linkOperations.delete(7);
|
||||||
|
myList.display(); // <-- 10(head) <--> 13(tail) -->
|
||||||
|
myList.displayBackwards();
|
||||||
|
|
||||||
|
linkOperations.insertOrdered(23,myList);
|
||||||
|
linkOperations.insertOrdered(67,myList);
|
||||||
|
linkOperations.insertOrdered(3,myList);
|
||||||
|
myList.display(); // <-- 3(head) <--> 10 <--> 13 <--> 23 <--> 67(tail) -->
|
||||||
|
linkOperations.insertElementByIndex(5, 1,myList);
|
||||||
|
myList.display(); // <-- 3(head) <--> 5 <--> 10 <--> 13 <--> 23 <--> 67(tail) -->
|
||||||
|
myList.displayBackwards();
|
||||||
|
linkOperations.reverse(); // <-- 67(head) <--> 23 <--> 13 <--> 10 <--> 5 <--> 3(tail) -->
|
||||||
|
myList.display();
|
||||||
|
|
||||||
|
linkOperations.clearList();
|
||||||
|
myList.display();
|
||||||
|
myList.displayBackwards();
|
||||||
|
linkOperations.insertHead(20,myList);
|
||||||
|
myList.display();
|
||||||
|
myList.displayBackwards();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This class implements the operations of the Link nodes.
|
||||||
|
*/
|
||||||
|
class LinkOperations{
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insert an element at the head
|
* Insert an element at the head
|
||||||
*
|
*
|
||||||
* @param x Element to be inserted
|
* @param x Element to be inserted
|
||||||
*/
|
*/
|
||||||
public void insertHead(int x) {
|
public void insertHead(int x,DoublyLinkedList doublyLinkedList) {
|
||||||
Link newLink = new Link(x); // Create a new link with a value attached to it
|
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
|
if (doublyLinkedList.isEmpty()) // Set the first element added to be the tail
|
||||||
{
|
{
|
||||||
tail = newLink;
|
tail = newLink;
|
||||||
} else {
|
} else {
|
||||||
@ -77,10 +214,10 @@ public class DoublyLinkedList {
|
|||||||
*
|
*
|
||||||
* @param x Element to be inserted
|
* @param x Element to be inserted
|
||||||
*/
|
*/
|
||||||
public void insertTail(int x) {
|
public void insertTail(int x,DoublyLinkedList doublyLinkedList) {
|
||||||
Link newLink = new Link(x);
|
Link newLink = new Link(x);
|
||||||
newLink.next = null; // currentTail(tail) newlink -->
|
newLink.next = null; // currentTail(tail) newlink -->
|
||||||
if (isEmpty()) { // Check if there are no elements in list then it adds first element
|
if (doublyLinkedList.isEmpty()) { // Check if there are no elements in list then it adds first element
|
||||||
tail = newLink;
|
tail = newLink;
|
||||||
head = tail;
|
head = tail;
|
||||||
} else {
|
} else {
|
||||||
@ -97,15 +234,15 @@ public class DoublyLinkedList {
|
|||||||
* @param x Element to be inserted
|
* @param x Element to be inserted
|
||||||
* @param index Index(from start) at which the element x to be inserted
|
* @param index Index(from start) at which the element x to be inserted
|
||||||
*/
|
*/
|
||||||
public void insertElementByIndex(int x, int index) {
|
public void insertElementByIndex(int x, int index,DoublyLinkedList doublyLinkedList) {
|
||||||
if (index > size) {
|
if (index > size) {
|
||||||
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
|
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
|
||||||
}
|
}
|
||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
insertHead(x);
|
insertHead(x,doublyLinkedList);
|
||||||
} else {
|
} else {
|
||||||
if (index == size) {
|
if (index == size) {
|
||||||
insertTail(x);
|
insertTail(x,doublyLinkedList);
|
||||||
} else {
|
} else {
|
||||||
Link newLink = new Link(x);
|
Link newLink = new Link(x);
|
||||||
Link previousLink = head; //
|
Link previousLink = head; //
|
||||||
@ -192,7 +329,7 @@ public class DoublyLinkedList {
|
|||||||
*
|
*
|
||||||
* @param x Element to be added
|
* @param x Element to be added
|
||||||
*/
|
*/
|
||||||
public void insertOrdered(int x) {
|
public void insertOrdered(int x,DoublyLinkedList doublyLinkedList) {
|
||||||
Link newLink = new Link(x);
|
Link newLink = new Link(x);
|
||||||
Link current = head;
|
Link current = head;
|
||||||
while (current != null && x > current.value) // Find the position to insert
|
while (current != null && x > current.value) // Find the position to insert
|
||||||
@ -201,9 +338,9 @@ public class DoublyLinkedList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (current == head) {
|
if (current == head) {
|
||||||
insertHead(x);
|
insertHead(x,doublyLinkedList);
|
||||||
} else if (current == null) {
|
} else if (current == null) {
|
||||||
insertTail(x);
|
insertTail(x,doublyLinkedList);
|
||||||
} else { // Before: 1 <--> 2(current) <--> 3
|
} else { // Before: 1 <--> 2(current) <--> 3
|
||||||
newLink.previous = current.previous; // 1 <-- newLink
|
newLink.previous = current.previous; // 1 <-- newLink
|
||||||
current.previous.next = newLink; // 1 <--> newLink
|
current.previous.next = newLink; // 1 <--> newLink
|
||||||
@ -230,14 +367,14 @@ public class DoublyLinkedList {
|
|||||||
--size;
|
--size;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void removeDuplicates(DoublyLinkedList l) {
|
public void removeDuplicates(DoublyLinkedList l) {
|
||||||
Link linkOne = l.head;
|
Link linkOne = l.head;
|
||||||
while (linkOne.next != null) { // list is present
|
while (linkOne.next != null) { // list is present
|
||||||
Link linkTwo = linkOne.next; // second link for comparison
|
Link linkTwo = linkOne.next; // second link for comparison
|
||||||
while (linkTwo.next != null) {
|
while (linkTwo.next != null) {
|
||||||
if (linkOne.value == linkTwo.value) // if there are duplicates values then
|
if (linkOne.value == linkTwo.value) // if there are duplicates values then
|
||||||
{
|
{
|
||||||
l.delete(linkTwo.value); // delete the link
|
delete(linkTwo.value); // delete the link
|
||||||
}
|
}
|
||||||
linkTwo = linkTwo.next; // go to next link
|
linkTwo = linkTwo.next; // go to next link
|
||||||
}
|
}
|
||||||
@ -247,8 +384,6 @@ public class DoublyLinkedList {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Reverses the list in place
|
* Reverses the list in place
|
||||||
*
|
|
||||||
* @param l the DoublyLinkedList to reverse
|
|
||||||
*/
|
*/
|
||||||
public void reverse() {
|
public void reverse() {
|
||||||
// Keep references to the head and tail
|
// Keep references to the head and tail
|
||||||
@ -282,116 +417,4 @@ public class DoublyLinkedList {
|
|||||||
size = 0;
|
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 the contents of the list in reverse order
|
|
||||||
*/
|
|
||||||
public void displayBackwards() {
|
|
||||||
Link current = tail;
|
|
||||||
while (current != null) {
|
|
||||||
current.displayLink();
|
|
||||||
current = current.previous;
|
|
||||||
}
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*
|
|
||||||
* @param value Value of node
|
|
||||||
*/
|
|
||||||
public Link(int value) {
|
|
||||||
this.value = 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) -->
|
|
||||||
myList.displayBackwards();
|
|
||||||
|
|
||||||
myList.insertTail(11);
|
|
||||||
myList.display(); // <-- 10(head) <--> 7 <--> 13 <--> 11(tail) -->
|
|
||||||
myList.displayBackwards();
|
|
||||||
|
|
||||||
myList.deleteTail();
|
|
||||||
myList.display(); // <-- 10(head) <--> 7 <--> 13(tail) -->
|
|
||||||
myList.displayBackwards();
|
|
||||||
|
|
||||||
myList.delete(7);
|
|
||||||
myList.display(); // <-- 10(head) <--> 13(tail) -->
|
|
||||||
myList.displayBackwards();
|
|
||||||
|
|
||||||
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.displayBackwards();
|
|
||||||
myList.reverse(); // <-- 67(head) <--> 23 <--> 13 <--> 10 <--> 5 <--> 3(tail) -->
|
|
||||||
myList.display();
|
|
||||||
|
|
||||||
myList.clearList();
|
|
||||||
myList.display();
|
|
||||||
myList.displayBackwards();
|
|
||||||
myList.insertHead(20);
|
|
||||||
myList.display();
|
|
||||||
myList.displayBackwards();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,51 +0,0 @@
|
|||||||
package com.thealgorithms.datastructures.lists;
|
|
||||||
|
|
||||||
public class RemoveDuplicateNodes {
|
|
||||||
|
|
||||||
public Node deleteDuplicates(Node head) {
|
|
||||||
// sentinel
|
|
||||||
Node sentinel = new Node(0, head);
|
|
||||||
|
|
||||||
// predecessor = the last node
|
|
||||||
// before the sublist of duplicates
|
|
||||||
Node pred = sentinel;
|
|
||||||
|
|
||||||
while (head != null) {
|
|
||||||
// if it's a beginning of duplicates sublist
|
|
||||||
// skip all duplicates
|
|
||||||
if (head.next != null && head.value == head.next.value) {
|
|
||||||
// move till the end of duplicates sublist
|
|
||||||
while (head.next != null && head.value == head.next.value) {
|
|
||||||
head = head.next;
|
|
||||||
}
|
|
||||||
// skip all duplicates
|
|
||||||
pred.next = head.next;
|
|
||||||
// otherwise, move predecessor
|
|
||||||
} else {
|
|
||||||
pred = pred.next;
|
|
||||||
}
|
|
||||||
|
|
||||||
// move forward
|
|
||||||
head = head.next;
|
|
||||||
}
|
|
||||||
return sentinel.next;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void print(Node head) {
|
|
||||||
Node temp = head;
|
|
||||||
while (temp != null && temp.next != null) {
|
|
||||||
System.out.print(temp.value + "->");
|
|
||||||
temp = temp.next;
|
|
||||||
}
|
|
||||||
if (temp != null) {
|
|
||||||
System.out.print(temp.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String arg[]) {
|
|
||||||
RemoveDuplicateNodes instance = new RemoveDuplicateNodes();
|
|
||||||
Node head = new Node(0, new Node(2, new Node(3, new Node(3, new Node(4)))));
|
|
||||||
head = instance.deleteDuplicates(head);
|
|
||||||
instance.print(head);
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,7 +5,7 @@ import java.util.StringJoiner;
|
|||||||
/**
|
/**
|
||||||
* https://en.wikipedia.org/wiki/Linked_list
|
* https://en.wikipedia.org/wiki/Linked_list
|
||||||
*/
|
*/
|
||||||
public class SinglyLinkedList {
|
public class SinglyLinkedList extends Node{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Head refer to the front of the list
|
* Head refer to the front of the list
|
||||||
@ -36,58 +36,10 @@ public class SinglyLinkedList {
|
|||||||
this.size = size;
|
this.size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Inserts an element at the head of the list
|
|
||||||
*
|
|
||||||
* @param x element to be added
|
|
||||||
*/
|
|
||||||
public void insertHead(int x) {
|
|
||||||
insertNth(x, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Insert an element at the tail of the list
|
|
||||||
*
|
|
||||||
* @param data element to be added
|
|
||||||
*/
|
|
||||||
public void insert(int data) {
|
|
||||||
insertNth(data, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inserts a new node at a specified position of the list
|
|
||||||
*
|
|
||||||
* @param data data to be stored in a new node
|
|
||||||
* @param position position at which a new node is to be inserted
|
|
||||||
*/
|
|
||||||
public void insertNth(int data, int position) {
|
|
||||||
checkBounds(position, 0, size);
|
|
||||||
Node newNode = new Node(data);
|
|
||||||
if (head == null) {
|
|
||||||
/* the list is empty */
|
|
||||||
head = newNode;
|
|
||||||
size++;
|
|
||||||
return;
|
|
||||||
} else if (position == 0) {
|
|
||||||
/* insert at the head of the list */
|
|
||||||
newNode.next = head;
|
|
||||||
head = newNode;
|
|
||||||
size++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Node cur = head;
|
|
||||||
for (int i = 0; i < position - 1; ++i) {
|
|
||||||
cur = cur.next;
|
|
||||||
}
|
|
||||||
newNode.next = cur.next;
|
|
||||||
cur.next = newNode;
|
|
||||||
size++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detects if there is a loop in the singly linked list using floy'd turtle
|
* Detects if there is a loop in the singly linked list using floy'd turtle
|
||||||
* and hare algorithm.
|
* and hare algorithm.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public boolean detectLoop() {
|
public boolean detectLoop() {
|
||||||
Node currentNodeFast = head;
|
Node currentNodeFast = head;
|
||||||
@ -104,27 +56,9 @@ public class SinglyLinkedList {
|
|||||||
return flag;
|
return flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Swaps nodes of two given values a and b.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public void swapNodes(int a, int b) {
|
|
||||||
Node currentNode = head;
|
|
||||||
Node temp = null;
|
|
||||||
while (currentNode != null) {
|
|
||||||
if (currentNode.next.value == a) {
|
|
||||||
temp = currentNode.next;
|
|
||||||
}
|
|
||||||
if (currentNode.next.value == b) {
|
|
||||||
currentNode.next = temp;
|
|
||||||
}
|
|
||||||
currentNode = currentNode.next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reverse a singly linked list from a given node till the end
|
* Reverse a singly linked list from a given node till the end
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
Node reverseList(Node node) {
|
Node reverseList(Node node) {
|
||||||
Node prev = null, curr = node, next;
|
Node prev = null, curr = node, next;
|
||||||
@ -138,58 +72,6 @@ public class SinglyLinkedList {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes a node at the head
|
|
||||||
*/
|
|
||||||
public void deleteHead() {
|
|
||||||
deleteNth(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes an element at the tail
|
|
||||||
*/
|
|
||||||
public void delete() {
|
|
||||||
deleteNth(size - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes an element at Nth position
|
|
||||||
*/
|
|
||||||
public void deleteNth(int position) {
|
|
||||||
checkBounds(position, 0, size - 1);
|
|
||||||
if (position == 0) {
|
|
||||||
Node destroy = head;
|
|
||||||
head = head.next;
|
|
||||||
destroy = null;
|
|
||||||
/* clear to let GC do its work */
|
|
||||||
size--;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Node cur = head;
|
|
||||||
for (int i = 0; i < position - 1; ++i) {
|
|
||||||
cur = cur.next;
|
|
||||||
}
|
|
||||||
|
|
||||||
Node destroy = cur.next;
|
|
||||||
cur.next = cur.next.next;
|
|
||||||
destroy = null; // clear to let GC do its work
|
|
||||||
|
|
||||||
size--;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param position to check position
|
|
||||||
* @param low low index
|
|
||||||
* @param high high index
|
|
||||||
* @throws IndexOutOfBoundsException if {@code position} not in range
|
|
||||||
* {@code low} to {@code high}
|
|
||||||
*/
|
|
||||||
public void checkBounds(int position, int low, int high) {
|
|
||||||
if (position > high || position < low) {
|
|
||||||
throw new IndexOutOfBoundsException(position + "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear all nodes in the list
|
* Clear all nodes in the list
|
||||||
*/
|
*/
|
||||||
@ -264,21 +146,6 @@ public class SinglyLinkedList {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return element at special index.
|
|
||||||
*
|
|
||||||
* @param index given index of element
|
|
||||||
* @return element at special index.
|
|
||||||
*/
|
|
||||||
public int getNth(int index) {
|
|
||||||
checkBounds(index, 0, size - 1);
|
|
||||||
Node cur = head;
|
|
||||||
for (int i = 0; i < index; ++i) {
|
|
||||||
cur = cur.next;
|
|
||||||
}
|
|
||||||
return cur.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringJoiner joiner = new StringJoiner("->");
|
StringJoiner joiner = new StringJoiner("->");
|
||||||
@ -332,6 +199,12 @@ public class SinglyLinkedList {
|
|||||||
assert true;
|
assert true;
|
||||||
/* this should happen */
|
/* this should happen */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Node instance = new Node();
|
||||||
|
Node head = new Node(0, new Node(2, new Node(3, new Node(3, new Node(4)))));
|
||||||
|
head = instance.deleteDuplicates(head);
|
||||||
|
instance.print(head);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -341,6 +214,18 @@ public class SinglyLinkedList {
|
|||||||
*/
|
*/
|
||||||
class Node {
|
class Node {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Head refer to the front of the list
|
||||||
|
*/
|
||||||
|
public Node head;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of SinglyLinkedList
|
||||||
|
*/
|
||||||
|
public int size;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The value of the node
|
* The value of the node
|
||||||
*/
|
*/
|
||||||
@ -373,4 +258,177 @@ class Node {
|
|||||||
this.value = value;
|
this.value = value;
|
||||||
this.next = next;
|
this.next = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Node deleteDuplicates(Node head) {
|
||||||
|
// sentinel
|
||||||
|
Node sentinel = new Node(0, head);
|
||||||
|
|
||||||
|
// predecessor = the last node
|
||||||
|
// before the sublist of duplicates
|
||||||
|
Node pred = sentinel;
|
||||||
|
|
||||||
|
while (head != null) {
|
||||||
|
// if it's a beginning of duplicates sublist
|
||||||
|
// skip all duplicates
|
||||||
|
if (head.next != null && head.value == head.next.value) {
|
||||||
|
// move till the end of duplicates sublist
|
||||||
|
while (head.next != null && head.value == head.next.value) {
|
||||||
|
head = head.next;
|
||||||
|
}
|
||||||
|
// skip all duplicates
|
||||||
|
pred.next = head.next;
|
||||||
|
// otherwise, move predecessor
|
||||||
|
} else {
|
||||||
|
pred = pred.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
// move forward
|
||||||
|
head = head.next;
|
||||||
|
}
|
||||||
|
return sentinel.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void print(Node head) {
|
||||||
|
Node temp = head;
|
||||||
|
while (temp != null && temp.next != null) {
|
||||||
|
System.out.print(temp.value + "->");
|
||||||
|
temp = temp.next;
|
||||||
|
}
|
||||||
|
if (temp != null) {
|
||||||
|
System.out.print(temp.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts an element at the head of the list
|
||||||
|
*
|
||||||
|
* @param x element to be added
|
||||||
|
*/
|
||||||
|
public void insertHead(int x) {
|
||||||
|
insertNth(x, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert an element at the tail of the list
|
||||||
|
*
|
||||||
|
* @param data element to be added
|
||||||
|
*/
|
||||||
|
public void insert(int data) {
|
||||||
|
insertNth(data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts a new node at a specified position of the list
|
||||||
|
*
|
||||||
|
* @param data data to be stored in a new node
|
||||||
|
* @param position position at which a new node is to be inserted
|
||||||
|
*/
|
||||||
|
public void insertNth(int data, int position) {
|
||||||
|
checkBounds(position, 0, size);
|
||||||
|
Node newNode = new Node(data);
|
||||||
|
if (head == null) {
|
||||||
|
/* the list is empty */
|
||||||
|
head = newNode;
|
||||||
|
size++;
|
||||||
|
return;
|
||||||
|
} else if (position == 0) {
|
||||||
|
/* insert at the head of the list */
|
||||||
|
newNode.next = head;
|
||||||
|
head = newNode;
|
||||||
|
size++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Node cur = head;
|
||||||
|
for (int i = 0; i < position - 1; ++i) {
|
||||||
|
cur = cur.next;
|
||||||
|
}
|
||||||
|
newNode.next = cur.next;
|
||||||
|
cur.next = newNode;
|
||||||
|
size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Swaps nodes of two given values a and b.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void swapNodes(int a, int b) {
|
||||||
|
Node currentNode = head;
|
||||||
|
Node temp = null;
|
||||||
|
while (currentNode != null) {
|
||||||
|
if (currentNode.next.value == a) {
|
||||||
|
temp = currentNode.next;
|
||||||
|
}
|
||||||
|
if (currentNode.next.value == b) {
|
||||||
|
currentNode.next = temp;
|
||||||
|
}
|
||||||
|
currentNode = currentNode.next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a node at the head
|
||||||
|
*/
|
||||||
|
public void deleteHead() {
|
||||||
|
deleteNth(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes an element at the tail
|
||||||
|
*/
|
||||||
|
public void delete() {
|
||||||
|
deleteNth(size - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes an element at Nth position
|
||||||
|
*/
|
||||||
|
public void deleteNth(int position) {
|
||||||
|
checkBounds(position, 0, size - 1);
|
||||||
|
if (position == 0) {
|
||||||
|
Node destroy = head;
|
||||||
|
head = head.next;
|
||||||
|
destroy = null;
|
||||||
|
/* clear to let GC do its work */
|
||||||
|
size--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Node cur = head;
|
||||||
|
for (int i = 0; i < position - 1; ++i) {
|
||||||
|
cur = cur.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node destroy = cur.next;
|
||||||
|
cur.next = cur.next.next;
|
||||||
|
destroy = null; // clear to let GC do its work
|
||||||
|
|
||||||
|
size--;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return element at special index.
|
||||||
|
*
|
||||||
|
* @param index given index of element
|
||||||
|
* @return element at special index.
|
||||||
|
*/
|
||||||
|
public int getNth(int index) {
|
||||||
|
checkBounds(index, 0, size - 1);
|
||||||
|
Node cur = head;
|
||||||
|
for (int i = 0; i < index; ++i) {
|
||||||
|
cur = cur.next;
|
||||||
|
}
|
||||||
|
return cur.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param position to check position
|
||||||
|
* @param low low index
|
||||||
|
* @param high high index
|
||||||
|
* @throws IndexOutOfBoundsException if {@code position} not in range
|
||||||
|
* {@code low} to {@code high}
|
||||||
|
*/
|
||||||
|
public void checkBounds(int position, int low, int high) {
|
||||||
|
if (position > high || position < low) {
|
||||||
|
throw new IndexOutOfBoundsException(position + "");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user