diff --git a/.gitea/workflows/gradle_build.yml b/.gitea/workflows/gradle_build.yml index f135547..89f015a 100644 --- a/.gitea/workflows/gradle_build.yml +++ b/.gitea/workflows/gradle_build.yml @@ -16,7 +16,7 @@ jobs: uses: actions/setup-java@v4 with: distribution: 'zulu' - java-version: '21' + java-version: '11' - name: Validate Gradle Wrapper uses: gradle/actions/wrapper-validation@v3 - name: Gradle build diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 0596ea7..b463382 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -10,6 +10,7 @@ diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..57e052a --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/modules/module4/Pricenton1.module4.test.iml b/.idea/modules/module4/Pricenton1.module4.test.iml new file mode 100644 index 0000000..2c66d96 --- /dev/null +++ b/.idea/modules/module4/Pricenton1.module4.test.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 6d70408..1844820 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,8 @@ { "java.compile.nullAnalysis.mode": "automatic", - "jdk.java.onSave.organizeImports": true + "jdk.java.onSave.organizeImports": true, + "java.configuration.updateBuildConfiguration": "interactive", + "cSpell.words": [ + "hithomelabs" + ] } \ No newline at end of file diff --git a/Roadmaps/datastructures.md b/Roadmaps/datastructures.md index e0513b9..de7cc7f 100644 --- a/Roadmaps/datastructures.md +++ b/Roadmaps/datastructures.md @@ -1,10 +1,18 @@ -#Data Structures +# Data Structures - 1. Stacks: - - Linear data structure - - Can have various implementations - - Should support (LIFO) - - Primitive implementation (Using arrays of primitive data types) - - Other implementations (Using linked lists) - 2. Queues: - \ No newline at end of file +1. Stacks: + - [API](../module4/src/main/java/com/hithomelabs/princeton1/module4/Stack.java) + - [Sample client](../clients/src/main/java/com/hithomelabs/clients/ArrayStackClient.java) + - Linear data structure + - Can have various implementations + - Should support (LIFO) + - [Primitive implementation](../module4/src/main/java/com/hithomelabs/princeton1/module4/ArrayStack.java) (Using arrays of primitive data types) + - [Other implementations](../module4/src/main/java/com/hithomelabs/princeton1/module4/LinkedStack.java) (Using linked lists) +2. Queues: + - [API](../module4/src/main/java/com/hithomelabs/princeton1/module4/Queue.java) + - [sample Client](../clients/src/main/java/com/hithomelabs/clients/LinkedQueueClient.java) + - Linear data structure. + - Can have various implementations. + - Should support FIFO. + - [Primitive implementation](../module4/src/main/java/com/hithomelabs/princeton1/module4/ArrayQueue.java) (Using array of primitive data types) + - Other implementation ([using linked lists](../module4/src/main/java/com/hithomelabs/princeton1/module4/LinkedQueue.java)) \ No newline at end of file diff --git a/clients/build.gradle b/clients/build.gradle index c9a970c..7ba5603 100644 --- a/clients/build.gradle +++ b/clients/build.gradle @@ -13,6 +13,12 @@ dependencies { testImplementation platform('org.junit:junit-bom:5.10.0') testImplementation 'org.junit.jupiter:junit-jupiter' implementation project(':module4') + implementation project(':module5') +} +java { + toolchain { + languageVersion = JavaLanguageVersion.of(11) + } } test { diff --git a/clients/src/main/java/com/hithomelabs/clients/ArrayQueueClient.java b/clients/src/main/java/com/hithomelabs/clients/module4/ArrayQueueClient.java similarity index 93% rename from clients/src/main/java/com/hithomelabs/clients/ArrayQueueClient.java rename to clients/src/main/java/com/hithomelabs/clients/module4/ArrayQueueClient.java index 7022367..3fd6900 100644 --- a/clients/src/main/java/com/hithomelabs/clients/ArrayQueueClient.java +++ b/clients/src/main/java/com/hithomelabs/clients/module4/ArrayQueueClient.java @@ -1,4 +1,4 @@ -package com.hithomelabs.clients; +package com.hithomelabs.clients.module4; import com.hithomelabs.princeton1.module4.ArrayQueue; import com.hithomelabs.princeton1.module4.Queue; diff --git a/clients/src/main/java/com/hithomelabs/clients/ArrayStackClient.java b/clients/src/main/java/com/hithomelabs/clients/module4/ArrayStackClient.java similarity index 93% rename from clients/src/main/java/com/hithomelabs/clients/ArrayStackClient.java rename to clients/src/main/java/com/hithomelabs/clients/module4/ArrayStackClient.java index 53a40c1..c233af8 100644 --- a/clients/src/main/java/com/hithomelabs/clients/ArrayStackClient.java +++ b/clients/src/main/java/com/hithomelabs/clients/module4/ArrayStackClient.java @@ -1,4 +1,4 @@ -package com.hithomelabs.clients; +package com.hithomelabs.clients.module4; import com.hithomelabs.princeton1.module4.ArrayStack; import com.hithomelabs.princeton1.module4.Stack; diff --git a/clients/src/main/java/com/hithomelabs/clients/LinkedQueueClient.java b/clients/src/main/java/com/hithomelabs/clients/module4/LinkedQueueClient.java similarity index 93% rename from clients/src/main/java/com/hithomelabs/clients/LinkedQueueClient.java rename to clients/src/main/java/com/hithomelabs/clients/module4/LinkedQueueClient.java index 008742c..8f39a87 100644 --- a/clients/src/main/java/com/hithomelabs/clients/LinkedQueueClient.java +++ b/clients/src/main/java/com/hithomelabs/clients/module4/LinkedQueueClient.java @@ -1,4 +1,4 @@ -package com.hithomelabs.clients; +package com.hithomelabs.clients.module4; import com.hithomelabs.princeton1.module4.LinkedQueue; import com.hithomelabs.princeton1.module4.Queue; diff --git a/clients/src/main/java/com/hithomelabs/clients/LinkedStackClient.java b/clients/src/main/java/com/hithomelabs/clients/module4/LinkedStackClient.java similarity index 94% rename from clients/src/main/java/com/hithomelabs/clients/LinkedStackClient.java rename to clients/src/main/java/com/hithomelabs/clients/module4/LinkedStackClient.java index 33cc4e9..b444d3d 100644 --- a/clients/src/main/java/com/hithomelabs/clients/LinkedStackClient.java +++ b/clients/src/main/java/com/hithomelabs/clients/module4/LinkedStackClient.java @@ -1,4 +1,4 @@ -package com.hithomelabs.clients; +package com.hithomelabs.clients.module4; import com.hithomelabs.princeton1.module4.LinkedStack; diff --git a/clients/src/main/java/com/hithomelabs/clients/module5/InsertionClient.java b/clients/src/main/java/com/hithomelabs/clients/module5/InsertionClient.java new file mode 100644 index 0000000..c0d75c7 --- /dev/null +++ b/clients/src/main/java/com/hithomelabs/clients/module5/InsertionClient.java @@ -0,0 +1,28 @@ +package com.hithomelabs.clients.module5; + +import com.hithomelabs.princeton1.module5.Insertion; +import com.hithomelabs.princeton1.module5.Apple; +import com.hithomelabs.princeton1.module5.Orange; + +public class InsertionClient { + + public static void main(String[] args){ + + Apple[] apples = new Apple[3]; + Orange[] oranges = new Orange[3]; + Insertion insertion = new Insertion<>(); + + apples[0] = new Apple(3); + apples[1] = new Apple(5); + apples[2] = new Apple(4); + insertion.sort(apples); + + //* * Sample output + for (int i = 0; i < apples.length; i++) + System.out.println(apples[i]); + } + + + + +} diff --git a/clients/src/main/java/com/hithomelabs/clients/module5/SelectionClient.java b/clients/src/main/java/com/hithomelabs/clients/module5/SelectionClient.java new file mode 100644 index 0000000..95c5ee7 --- /dev/null +++ b/clients/src/main/java/com/hithomelabs/clients/module5/SelectionClient.java @@ -0,0 +1,66 @@ +package com.hithomelabs.clients.module5; + +import com.hithomelabs.princeton1.module5.Selection; + +import java.util.ArrayList; + +public class SelectionClient { + + + + public static void main(String[] args){ + + Apple[] apples = new Apple[3]; + Orange[] oranges = new Orange[3]; + Selection selection = new Selection(); + + apples[0] = new Apple(3); + apples[1] = new Apple(5); + apples[2] = new Apple(4); + selection.sort(apples); + + //* * Sample output + for (int i = 0; i < apples.length; i++) + System.out.println(apples[i]); + + oranges[0] = new Orange(4); + oranges[1] = new Orange(1); + // * Should give runtime exception as ClassCastException is a runtime exception + //selection.sort(oranges); + Selection selection2 = new Selection(); + // * Should result in a compile time exception, as casting to Orange will fail + //selection2.sort(apples); + } + + private static class Orange{ + private int size; + Orange(int size){ + this.size = size; + } + + @Override + public String toString() { + return "An orange of size "+size; + } + } + + private static class Apple implements Comparable{ + private int size; + + Apple(int size){ + this.size = size; + } + + @Override + public String toString() { + return "An apple of size "+size; + } + + @Override + public int compareTo(Apple that) { + if (this.size < that.size) return -1; + else if (this.size == that.size)return 0; + else return 1; + } + } +} diff --git a/clients/src/main/java/com/hithomelabs/clients/module5/ShellClient.java b/clients/src/main/java/com/hithomelabs/clients/module5/ShellClient.java new file mode 100644 index 0000000..504eede --- /dev/null +++ b/clients/src/main/java/com/hithomelabs/clients/module5/ShellClient.java @@ -0,0 +1,29 @@ +package com.hithomelabs.clients.module5; + +import com.hithomelabs.princeton1.module5.Apple; +import com.hithomelabs.princeton1.module5.Shell; + +import java.util.Arrays; +import java.util.Random; + +public class ShellClient { + + public static void main(String[] args) { + + int size = 100; + Apple[] apples = new Apple[size]; + Shell shell = new Shell(); + + for (int i = 0; i < apples.length; i++) { + apples[i] = new Apple(new Random().nextInt(1000)); + } + Apple[] applesCopy = Arrays.copyOf(apples, size); + shell.sort(apples); + shell.insertionSort(applesCopy); + + //* * Sample output + for (int i = 0; i < apples.length; i++) + System.out.println(apples[i]); + } +} + diff --git a/module4/src/main/java/com/hithomelabs/princeton1/module4/ArrayQueue.java b/module4/src/main/java/com/hithomelabs/princeton1/module4/ArrayQueue.java index 4e8988e..8576647 100644 --- a/module4/src/main/java/com/hithomelabs/princeton1/module4/ArrayQueue.java +++ b/module4/src/main/java/com/hithomelabs/princeton1/module4/ArrayQueue.java @@ -1,8 +1,9 @@ package com.hithomelabs.princeton1.module4; -import javax.annotation.Nonnull; import java.util.Iterator; +import javax.annotation.Nonnull; + public class ArrayQueue extends Queue{ // insertion from tail, removal from head diff --git a/module4/src/main/java/com/hithomelabs/princeton1/module4/ArrayStack.java b/module4/src/main/java/com/hithomelabs/princeton1/module4/ArrayStack.java index 0ae2eb6..93b3f30 100644 --- a/module4/src/main/java/com/hithomelabs/princeton1/module4/ArrayStack.java +++ b/module4/src/main/java/com/hithomelabs/princeton1/module4/ArrayStack.java @@ -1,13 +1,13 @@ package com.hithomelabs.princeton1.module4; -import javax.annotation.Nonnull; import java.util.Iterator; +import javax.annotation.Nonnull; // Concrete implementation of stack using arrays // Creating a generic stack of type E public class ArrayStack extends Stack { // Capacity and size are two variables, capacity determines total capacity of array, capacity defaults at 10 - // Everytime size == capacity, capacity = 2 * capacity + // every time size == capacity, capacity = 2 * capacity private static final int DEFAULT_CAPACITY = 10; private int capacity; private int size; @@ -18,7 +18,7 @@ public class ArrayStack extends Stack { arr = (E[]) new Object[this.capacity]; } - // Constructor chaining, default constructor will call parametrised constructor with default initial capacity 10 + // Constructor chaining, default constructor will call parametrized constructor with default initial capacity 10 public ArrayStack(){ this(DEFAULT_CAPACITY); } @@ -64,7 +64,7 @@ public class ArrayStack extends Stack { } private void checkResize() { - if (size < capacity / 4 && capacity >= 40){ + if (size < capacity / 4 && capacity >= 20){ capacity = capacity / 2; changeCapacity(capacity); } diff --git a/module4/src/main/java/com/hithomelabs/princeton1/module4/LinkedQueue.java b/module4/src/main/java/com/hithomelabs/princeton1/module4/LinkedQueue.java index ec37bbe..b7e62ff 100644 --- a/module4/src/main/java/com/hithomelabs/princeton1/module4/LinkedQueue.java +++ b/module4/src/main/java/com/hithomelabs/princeton1/module4/LinkedQueue.java @@ -60,7 +60,7 @@ public class LinkedQueue extends Queue{ Node current = head; @Override public boolean hasNext() { - return current != tail; + return current != null; } @Override diff --git a/module4/src/test/java/com/hithomelabs/princeton1/module4/ArrayQueueTest.java b/module4/src/test/java/com/hithomelabs/princeton1/module4/ArrayQueueTest.java new file mode 100644 index 0000000..67ccd0e --- /dev/null +++ b/module4/src/test/java/com/hithomelabs/princeton1/module4/ArrayQueueTest.java @@ -0,0 +1,76 @@ +package com.hithomelabs.princeton1.module4; + +import java.util.Iterator; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + + +import static org.junit.jupiter.api.Assertions.*; + +class ArrayQueueTest { + + private Queue queue; + + @BeforeEach + void setUp() { + queue = new ArrayQueue(); + } + + @AfterEach + void tearDown() { + queue = null; + } + + @Test + @DisplayName("Empty queue must return size zero") + public void testEmptyQueueSize(){ + assertEquals(0, queue.size()); + } + + @Test + @DisplayName("Enqueuing must work as expected") + public void testEnqueue(){ + queue.enqueue(1); + queue.enqueue(2); + assertEquals(2,queue.size()); + Iterator iterator = queue.iterator(); + assertEquals(1, iterator.next()); + assertEquals(2, iterator.next()); + } + + @Test + @DisplayName("Dequeueing must work as expected") + public void testDequeue(){ + queue.enqueue(1); + queue.enqueue(2); + assertEquals(1, queue.dequeue()); + queue.enqueue(3); + assertEquals(2, queue.size()); + assertEquals(2, queue.dequeue()); + assertEquals(3, queue.dequeue()); + assertEquals(0, queue.size()); + assertNull(queue.dequeue()); + } + + @Test + @DisplayName("Testing resizable array and iterator") + public void testResize(){ + for(int i = 0; i < 21; i++) + queue.enqueue(i); + for(int i = 0; i < 13; i++){ + queue.dequeue(); + } + assertEquals(13, queue.dequeue()); + assertEquals(7,queue.size()); + Integer[] arr = new Integer[queue.size()]; + Iterator iterator = queue.iterator(); + int count = 0; + while(iterator.hasNext()){ + arr[count++] = iterator.next(); + } + assertArrayEquals(new Integer[]{14, 15, 16, 17, 18, 19, 20}, arr); + } + +} \ No newline at end of file diff --git a/module4/src/test/java/com/hithomelabs/princeton1/module4/ArrayStackTest.java b/module4/src/test/java/com/hithomelabs/princeton1/module4/ArrayStackTest.java new file mode 100644 index 0000000..c9ab765 --- /dev/null +++ b/module4/src/test/java/com/hithomelabs/princeton1/module4/ArrayStackTest.java @@ -0,0 +1,85 @@ +package com.hithomelabs.princeton1.module4; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.Iterator; + +import static org.junit.jupiter.api.Assertions.*; + +class ArrayStackTest { + + private Stack stack; + + @BeforeEach + void setUp() { + stack = new ArrayStack(); + } + + @AfterEach + void tearDown() { + stack = null; + } + + @Test + @DisplayName("Empty stack must return size zero") + public void testEmptyStackSize(){ + assertEquals(0, stack.size()); + } + + @Test + @DisplayName("Push must work as expected") + public void testEnqueue(){ + stack.push("Hello"); + stack.push("World"); + assertEquals(2,stack.size()); + Iterator iterator = stack.iterator(); + assertEquals("Hello", iterator.next()); + assertEquals("World", iterator.next()); + } + + @Test + @DisplayName("Pop must work as expected") + public void testDequeue(){ + stack.push("hello"); + stack.push("world"); + assertEquals("world", stack.pop()); + stack.push("I"); + assertEquals(2, stack.size()); + assertEquals("I", stack.pop()); + assertEquals("hello", stack.pop()); + assertEquals(0, stack.size()); + assertNull(stack.pop()); + } + + @Test + @DisplayName("Testing resizable array and iterator") + public void testResize(){ + stack.push("Hello"); + stack.push("world"); + stack.push("I"); + stack.push("am"); + stack.push("testing"); + stack.push("my"); + stack.push("implementation"); + stack.push("of"); + stack.push("Stacks"); + stack.push("Data"); + stack.push("Structure"); + assertEquals("Structure", stack.pop()); + int counter = 6; + while(counter-- > 0) + stack.pop(); + assertEquals(4,stack.size()); + String[] arr = new String[stack.size()]; + Iterator iterator = stack.iterator(); + int count = 0; + while(iterator.hasNext()){ + arr[count++] = iterator.next(); + } + assertArrayEquals(new String[]{"Hello", "world", "I", "am"}, arr); + } + +} \ No newline at end of file diff --git a/module4/src/test/java/com/hithomelabs/princeton1/module4/LinkedQueueTest.java b/module4/src/test/java/com/hithomelabs/princeton1/module4/LinkedQueueTest.java new file mode 100644 index 0000000..915cf4a --- /dev/null +++ b/module4/src/test/java/com/hithomelabs/princeton1/module4/LinkedQueueTest.java @@ -0,0 +1,76 @@ +package com.hithomelabs.princeton1.module4; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.Iterator; + +import static org.junit.jupiter.api.Assertions.*; + +class LinkedQueueTest { + + private Queue queue; + + @BeforeEach + void setUp() { + queue = new LinkedQueue<>(); + } + + @AfterEach + void tearDown() { + queue = null; + } + + + @Test + @DisplayName("Empty queue must return size zero") + public void testEmptyQueueSize(){ + assertEquals(0, queue.size()); + } + + @Test + @DisplayName("Enqueuing must work as expected") + public void testEnqueue(){ + queue.enqueue(1); + queue.enqueue(2); + assertEquals(2,queue.size()); + Iterator iterator = queue.iterator(); + assertEquals(1, iterator.next()); + assertEquals(2, iterator.next()); + } + + @Test + @DisplayName("Dequeueing must work as expected") + public void testDequeue(){ + queue.enqueue(1); + queue.enqueue(2); + assertEquals(1, queue.dequeue()); + queue.enqueue(3); + assertEquals(2, queue.size()); + assertEquals(2, queue.dequeue()); + assertEquals(3, queue.dequeue()); + assertEquals(0, queue.size()); + assertNull(queue.dequeue()); + } + + @Test + @DisplayName("Testing resizable array and iterator") + public void testResize(){ + for(int i = 0; i < 21; i++) + queue.enqueue(i); + for(int i = 0; i < 13; i++){ + queue.dequeue(); + } + assertEquals(13, queue.dequeue()); + assertEquals(7,queue.size()); + Integer[] arr = new Integer[queue.size()]; + Iterator iterator = queue.iterator(); + int count = 0; + while(iterator.hasNext()){ + arr[count++] = iterator.next(); + } + assertArrayEquals(new Integer[]{14, 15, 16, 17, 18, 19, 20}, arr); + } +} \ No newline at end of file diff --git a/module5/build.gradle b/module5/build.gradle new file mode 100644 index 0000000..6b1dd5d --- /dev/null +++ b/module5/build.gradle @@ -0,0 +1,23 @@ +plugins { + id 'java' +} + +group = 'com.hithomelabs.princeton1.module5' +version = 'unspecified' + +repositories { + mavenCentral() +} + +dependencies { + testImplementation platform('org.junit:junit-bom:5.10.0') + testImplementation 'org.junit.jupiter:junit-jupiter' +} +java { + toolchain { + languageVersion = JavaLanguageVersion.of(11) + } +} +test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/module5/src/main/java/com/hithomelabs/princeton1/module5/AbstractCustomSorts.java b/module5/src/main/java/com/hithomelabs/princeton1/module5/AbstractCustomSorts.java new file mode 100644 index 0000000..647b506 --- /dev/null +++ b/module5/src/main/java/com/hithomelabs/princeton1/module5/AbstractCustomSorts.java @@ -0,0 +1,17 @@ +package com.hithomelabs.princeton1.module5; + +public abstract class AbstractCustomSorts { + + public abstract void sort(E[] arr); + + public void exch(E[] arr, int j, int i) { + E temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + } + + public boolean less(Comparable e1, E e2) { + return e1.compareTo(e2) < 0; + } + +} diff --git a/module5/src/main/java/com/hithomelabs/princeton1/module5/Apple.java b/module5/src/main/java/com/hithomelabs/princeton1/module5/Apple.java new file mode 100644 index 0000000..131b5bb --- /dev/null +++ b/module5/src/main/java/com/hithomelabs/princeton1/module5/Apple.java @@ -0,0 +1,37 @@ +package com.hithomelabs.princeton1.module5; + +import java.util.Objects; + +public class Apple implements Comparable { + private int size; + + public Apple(int size) { + this.size = size; + } + + @Override + public boolean equals(Object obj) { + if(this == obj) return true; + if (obj == null || this.getClass() != obj.getClass()) + return false; + Apple that = (Apple) obj; + return Objects.equals(this.size, that.size); + } + + @Override + public int hashCode() { + return Objects.hash(size); + } + + @Override + public String toString() { + return "An apple of size " + size; + } + + @Override + public int compareTo(Apple that) { + if (this.size < that.size) return -1; + else if (this.size == that.size) return 0; + else return 1; + } +} diff --git a/module5/src/main/java/com/hithomelabs/princeton1/module5/Insertion.java b/module5/src/main/java/com/hithomelabs/princeton1/module5/Insertion.java new file mode 100644 index 0000000..49ce313 --- /dev/null +++ b/module5/src/main/java/com/hithomelabs/princeton1/module5/Insertion.java @@ -0,0 +1,23 @@ +package com.hithomelabs.princeton1.module5; + +public class Insertion extends AbstractCustomSorts { + + public void sort(E[] arr){ + if (arr == null) return; + else{ + int N = arr.length; + // * * swap arr[i] with each element greater to it's left + for (int i = 1; i < N; i++){ + int j = i; + while(j >= 1 && less((Comparable)arr[j], arr[j-1])){ + exch(arr, j, j-1); + j = j-1; + } + } + } + + } + + + } + diff --git a/module5/src/main/java/com/hithomelabs/princeton1/module5/Orange.java b/module5/src/main/java/com/hithomelabs/princeton1/module5/Orange.java new file mode 100644 index 0000000..02db021 --- /dev/null +++ b/module5/src/main/java/com/hithomelabs/princeton1/module5/Orange.java @@ -0,0 +1,14 @@ +package com.hithomelabs.princeton1.module5; + +public class Orange { + private int size; + + public Orange(int size) { + this.size = size; + } + + @Override + public String toString() { + return "An orange of size " + size; + } +} diff --git a/module5/src/main/java/com/hithomelabs/princeton1/module5/Selection.java b/module5/src/main/java/com/hithomelabs/princeton1/module5/Selection.java new file mode 100644 index 0000000..3b0a0c1 --- /dev/null +++ b/module5/src/main/java/com/hithomelabs/princeton1/module5/Selection.java @@ -0,0 +1,23 @@ +package com.hithomelabs.princeton1.module5; + + +public class Selection extends AbstractCustomSorts{ + + /* + * * Selection sort "selects" the smallest element and swaps it with arr[0] of the array + * * Then proceeds to do the same swapping arr[i] with arr[i:arr.length-1] + */ + public void sort(E[] arr){ + if (arr == null) return; + Comparable[] arr1 = (Comparable[]) arr; + for(int i = 0; i < arr1.length - 1; i++){ + int minIndex = i; + for(int j = i+1; j < arr.length; j ++){ + if (less((Comparable) arr[j], arr[minIndex])) minIndex = j; + } + exch(arr, i, minIndex); + } + } + +} + diff --git a/module5/src/main/java/com/hithomelabs/princeton1/module5/Shell.java b/module5/src/main/java/com/hithomelabs/princeton1/module5/Shell.java new file mode 100644 index 0000000..97a08ff --- /dev/null +++ b/module5/src/main/java/com/hithomelabs/princeton1/module5/Shell.java @@ -0,0 +1,66 @@ +package com.hithomelabs.princeton1.module5; + +public class Shell extends AbstractCustomSorts { + + // * * sample metadata class to compare no. of sorts and compares, shell sort vs insertion sort + private class MetaData{ + + int compares; + int swaps; + } + +/* + * * We will be performing h sort + * * Suppose or function to determine subsequent values of h is: + * * h(i+1) = 3*h(i) + 1; h = 1, 4, 13, 40, 121, .... + * * h will never be perfectly divisible by 3; further dividing h[i]/3 will give h[i-1] + * * We want to h-sort using larges value of h smaller than N, followed by smaller values of h + * * If N = 100, we h-sort by 40, meaning every 40th element will be in order + * * Then we h-sort by 13, meaning every 40th and every 13th element will be in order and every 40th element will be in order + * * Finally, when h will come out as 1, it will be same as insertion sort, however by that time the array will almost be sorted + * * Insertion sort for an almost sorted array is linear time. + * * As a case study we implement both insertion sort and selection sort for an array of 1000 nos. + * * And check number of compares and no. of exchanges in each case + */ + @Override + public void sort(E[] arr) { + MetaData metaData = new MetaData(); + int N = arr.length; + int h = 1; + // * * Calculates the largest value of h greater than n + while (3 * h + 1 < N) { + h = 3 * h + 1; + } + while (h >= 1) { + h = hsort(arr, h, metaData); + h = h / 3; + } + System.out.println("Array sorted (shell sort) with " + metaData.compares + " compares and " + metaData.swaps + " swaps"); + } + + private int hsort(E[] arr, int h, MetaData metadata) { + int N = arr.length; + for(int i = h; i < N; i++){ + int j = i; + ++metadata.compares; + while(j >= h && less((Comparable) arr[j], arr[j-h])){ + ++metadata.swaps; + exch(arr, j, j-h); + j = j - h; + ++metadata.compares; + } + } + return h; + } + /* + ! sample implementation of insertion sort as h-sort of h = 1 + * Will just be comparing the number of saps taken across both implementations + */ + public void insertionSort(E[] arr){ + MetaData metaData = new MetaData(); + int h = 1; + h = hsort(arr, h, metaData); + System.out.println("Array sorted (insertion sort) with " + metaData.compares + " compares and " + metaData.swaps + " swaps"); + } + +} diff --git a/module5/src/test/java/com/hithomelabs/princeton1/module5/SortTest.java b/module5/src/test/java/com/hithomelabs/princeton1/module5/SortTest.java new file mode 100644 index 0000000..d0b2e4a --- /dev/null +++ b/module5/src/test/java/com/hithomelabs/princeton1/module5/SortTest.java @@ -0,0 +1,63 @@ +package com.hithomelabs.princeton1.module5; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.Random; + +import static org.junit.jupiter.api.Assertions.*; + +class SortTest { + + private ArrayList apples; + private AbstractCustomSorts sortingAlgorithm; + private Random random; + + @BeforeEach + void setUp() { + apples = new ArrayList(); + //sortingAlgorithm = new Selection(); + random = new Random(); + } + + private void testSort(AbstractCustomSorts sortingAlgorithm) { + for (int i = 0; i < 100; i++) + apples.add(new Apple(random.nextInt(100))); + Apple[] arr = apples.toArray(new Apple[apples.size()]); + apples.sort(null); + Apple[] sorted = apples.toArray(new Apple[apples.size()]); + sortingAlgorithm.sort(arr); + assertArrayEquals(sorted, arr); + } + + @Test + @DisplayName("Testing Insertion sort functionality") + public void testInsertionSort() { + sortingAlgorithm = new Insertion(); + testSort(sortingAlgorithm); + } + + @Test + @DisplayName("Testing Selection sort functionality") + public void testSelectionSort() { + sortingAlgorithm = new Selection(); + testSort(sortingAlgorithm); + } + + @Test + @DisplayName("Testing Shell sort functionality") + public void testShellSort() { + sortingAlgorithm = new Shell<>(); + testSort(sortingAlgorithm); + } + + + @AfterEach + void tearDown() { + sortingAlgorithm = null; + apples = null; + } +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index cf1c802..f786f9b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -13,4 +13,5 @@ plugins { rootProject.name = 'Pricenton1' include('module4') include 'clients' +include 'module5'