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 8576647..9e10c4a 100644 --- a/module4/src/main/java/com/hithomelabs/princeton1/module4/ArrayQueue.java +++ b/module4/src/main/java/com/hithomelabs/princeton1/module4/ArrayQueue.java @@ -6,23 +6,11 @@ import javax.annotation.Nonnull; public class ArrayQueue extends Queue{ - // insertion from tail, removal from head - public static final int DEFAULT_CAPACITY = 10; - private int capacity; - private int tail; - private int head; + private E[] queueArray = (E[]) new Object[5]; + private int startPtr; + private int endPtr; private int size; - private E[] arr; - - public ArrayQueue(){ - this(DEFAULT_CAPACITY); - } - - public ArrayQueue(int capacity){ - this.capacity = capacity; - arr = (E[]) new Object[this.capacity]; - size = 0; - } + private int queueArrayLength = queueArray.length; @Override public boolean isEmpty() { @@ -31,49 +19,25 @@ public class ArrayQueue extends Queue{ @Override public E dequeue() { - if(isEmpty()) + if(isEmpty()){ return null; - else{ - E element = arr[head]; - // Garbage collection - arr[head] = null; - head = (head+1)%capacity; - size = size - 1; - if(capacity >= 40 && size < capacity/4){ - capacity = capacity/2; - resize(capacity, capacity*2); - } - return element; } + E currentValue = queueArray[startPtr % queueArrayLength]; + queueArray[startPtr++ % queueArrayLength] = null; + size--; + if(size() < queueArrayLength/4){ + changeArraySize(queueArrayLength/2); + } + return currentValue; } @Override public void enqueue(E element) { - // We plan capacity expansion if needed - if (size == capacity){ - capacity = capacity * 2; - resize(capacity, capacity/2); + queueArray[endPtr++ % queueArrayLength] = element; + size++; + if(size == queueArrayLength){ + changeArraySize(queueArrayLength*2); } - arr[tail] = element; - tail = (tail + 1) % capacity; - ++size; - } - - // When resize takes place always the original array is full, so copy the complete array as is - private void resize(int capacity, int oldCapacity) { - E[] resizedArr = (E[]) new Object[capacity]; - for(int i = 0; i < size; i++) { - resizedArr[i] = arr[head]; - // halving because capacity has now doubled - arr[head] = null; - head = (head + 1) % oldCapacity; - } - arr = resizedArr; - // When resizing takes place, we bring the head to 0 and the tail to size - // tail is where new inserts will be made and head will be where elements will be removed - tail = size; - head = 0; - } @Override @@ -81,24 +45,37 @@ public class ArrayQueue extends Queue{ return size; } - @Override - @Nonnull - public Iterator iterator() { - return new Iterator() { - int counter = size; - int pointer = head; - @Override - public boolean hasNext() { - return counter != 0; - } + private void changeArraySize(int targetSize){ + E[] tempArray = queueArray; + int oldArraySize = tempArray.length; + queueArray = (E[]) new Object[targetSize]; + int j = 0; - @Override - public E next() { - E element = arr[pointer]; - pointer = (pointer + 1)% capacity; - --counter; - return element; - } - }; + for(int i=0; i iterator() { + return new QueueArrayIterator(); + } + + private class QueueArrayIterator implements Iterator{ + + private int iteratorIndex = startPtr; + + @Override + public boolean hasNext() { + return iteratorIndex % queueArrayLength < endPtr % queueArrayLength; + } + + @Override + public E next() { + return queueArray[iteratorIndex++ % queueArrayLength]; + } } } 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 93b3f30..a26b414 100644 --- a/module4/src/main/java/com/hithomelabs/princeton1/module4/ArrayStack.java +++ b/module4/src/main/java/com/hithomelabs/princeton1/module4/ArrayStack.java @@ -6,93 +6,68 @@ import javax.annotation.Nonnull; // 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 - // every time size == capacity, capacity = 2 * capacity - private static final int DEFAULT_CAPACITY = 10; - private int capacity; - private int size; - private E[] arr; - - public ArrayStack(int capacity){ - this.capacity = capacity; - arr = (E[]) new Object[this.capacity]; - } - - // Constructor chaining, default constructor will call parametrized constructor with default initial capacity 10 - public ArrayStack(){ - this(DEFAULT_CAPACITY); - } + E[] stackArray = (E[]) new Object[1]; + private int index = 0; + private int arrayLength = stackArray.length; @Override public boolean isEmpty() { - return size == 0; + return index == 0; } - private void changeCapacity(int newCapacity){ - E[] resizedArr = (E[]) new Object[newCapacity]; - for (int i = 0; i < size; i++) - resizedArr[i] = arr[i]; - arr = resizedArr; - } - - private void incrementSize(){ - if (size == capacity){ - capacity = 2 * capacity; - changeCapacity(capacity); - } - } - - // Push always happens at the end of the stack - // Say the size of the stack is 1, new element gets inserted at 1 @Override public void push(E element) { - // Lazy approach, we assume size to always be lesser than capacity - incrementSize(); - arr[size++] = element; + if(index == arrayLength){ + changeArraySize(arrayLength*2); + } + stackArray[index] = element; + index++; } @Override public E pop() { - if (isEmpty()) + if(index == 0){ return null; - else{ - E e = arr[--size]; - arr[size] = null; - checkResize(); - return e; } - } - - private void checkResize() { - if (size < capacity / 4 && capacity >= 20){ - capacity = capacity / 2; - changeCapacity(capacity); + index--; + if(index < arrayLength/4){ + changeArraySize(arrayLength/2); } + E temp = stackArray[index]; + stackArray[index] = null; + return temp; } @Override public int size() { - return size; + return index; } - @Override @Nonnull + @Override public Iterator iterator() { - return new Iterator() { + return new StackIterator(); + } - int current = 0; + private void changeArraySize(int intendedSize){ + E[] tempArray = stackArray; + int oldArraySize = stackArray.length; + stackArray = (E[]) new Object[intendedSize]; + arrayLength = stackArray.length; + System.arraycopy(tempArray, 0, stackArray, 0, Math.min(oldArraySize, arrayLength)); + } - @Override - public boolean hasNext() { - return current != size; - } + private class StackIterator implements Iterator{ + private int iteratorIndex = 0; - @Override - public E next() { - E element = arr[current]; - current = current + 1; - return element; - } - }; + @Override + public boolean hasNext() { + return stackArray[iteratorIndex] != null; + } + + @Override + public E next() { + return stackArray[iteratorIndex++]; + } } } 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 b7e62ff..f4d83e9 100644 --- a/module4/src/main/java/com/hithomelabs/princeton1/module4/LinkedQueue.java +++ b/module4/src/main/java/com/hithomelabs/princeton1/module4/LinkedQueue.java @@ -5,70 +5,76 @@ import java.util.Iterator; public class LinkedQueue extends Queue{ - Node head; - Node tail; - int size; + Node start = null; + Node end = null; - private class Node{ - E value; - Node next; + static private class Node{ + E data; + Node next; - Node(E value){ - this.value = value; + private Node(E element){ + data=element; + next=null; } } @Override public boolean isEmpty() { - return size==0; + return start == null; } @Override public E dequeue() { if(isEmpty()) return null; - E element = head.value; - // Only a single element is present - if (head == tail){ - tail = null; - } - head = head.next; - --size; - return element; + E currentValue = start.data; + start = start.next; + if(isEmpty()) + end = null; + return currentValue; } @Override public void enqueue(E element) { - Node newNode = new Node(element); + Node new_node = new Node(element); if(isEmpty()) - head = newNode; + start = new_node; else - tail.next = newNode; - tail = newNode; - ++size; + end.next = new_node; + end = new_node; } @Override public int size() { + int size = 0; + Node sizePtr = start; + while (sizePtr != null) { + sizePtr = sizePtr.next; + size++; + } return size; } - @Override @Nonnull + @Override public Iterator iterator() { - return new Iterator() { - Node current = head; - @Override - public boolean hasNext() { - return current != null; - } + return new LinkedQueueIterator(); + } - @Override - public E next() { - E element = current.value; - current = current.next; - return element; - } - }; + private class LinkedQueueIterator implements Iterator{ + + Node traversePtr = start; + + @Override + public boolean hasNext() { + return traversePtr != null; + } + + @Override + public E next() { + E currentValue = traversePtr.data; + traversePtr = traversePtr.next; + return currentValue; + } } } diff --git a/module4/src/main/java/com/hithomelabs/princeton1/module4/LinkedStack.java b/module4/src/main/java/com/hithomelabs/princeton1/module4/LinkedStack.java index 6c7c398..97afc76 100644 --- a/module4/src/main/java/com/hithomelabs/princeton1/module4/LinkedStack.java +++ b/module4/src/main/java/com/hithomelabs/princeton1/module4/LinkedStack.java @@ -1,72 +1,71 @@ package com.hithomelabs.princeton1.module4; + +import javax.annotation.Nonnull; import java.util.Iterator; // Creating a concrete linked Implementation of Stack public class LinkedStack extends Stack{ - // No need for an explicit constructor as size will be initialized to 0 and root to null - private int size; - private Node first; + static class Node{ + E data; + Node next; - // By default instance variables are package private - private class Node{ - E value; - Node next; + Node(E data) { + this.data = data; + this.next = null; + } } - // Will return true if size is 0 + Node head = null; + int stackLength = 0; + @Override public boolean isEmpty() { - return (this.size == 0); + return head == null; } - // Adds an element to the start of a linked list @Override public void push(E element) { - Node newNode = new Node(); - newNode.value = element; - newNode.next = first; - first = newNode; - this.size = this.size + 1; + Node new_node = new Node(element); + new_node.next = head; + head = new_node; + stackLength++; } @Override public E pop() { - if (this.isEmpty()) + if(stackLength == 0) return null; - else{ - Node toBePopped = first; - first = first.next; - this.size = this.size - 1; - return toBePopped.value; - } + E currentValue = head.data; + head = head.next; + return currentValue; } @Override public int size() { - return this.size; + return stackLength; } + @Nonnull @Override public Iterator iterator() { - return new Iterator() { - - // Internal classes can access outer objects - Node current = first; - @Override - public boolean hasNext() { - return current != null; - } - - @Override - public E next() { - E element = current.value; - current = current.next; - return element; - } - }; + return new LinkedlistIterator(); } + private class LinkedlistIterator implements Iterator{ + Node iteratorPtr = head; + @Override + public boolean hasNext() { + return iteratorPtr.next != null; + } + + @Override + public E next() { + E currentValue = iteratorPtr.data; + iteratorPtr = iteratorPtr.next; + return currentValue; + } + } } diff --git a/module5/src/main/java/com/hithomelabs/princeton1/module5/AbstractCustomSorts.java b/module5/src/main/java/com/hithomelabs/princeton1/module5/AbstractCustomSorts.java index 647b506..6fa211b 100644 --- a/module5/src/main/java/com/hithomelabs/princeton1/module5/AbstractCustomSorts.java +++ b/module5/src/main/java/com/hithomelabs/princeton1/module5/AbstractCustomSorts.java @@ -4,12 +4,14 @@ public abstract class AbstractCustomSorts { public abstract void sort(E[] arr); + // TODO: Implement this method public void exch(E[] arr, int j, int i) { E temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } + // TODO: Implement this method public boolean less(Comparable e1, E e2) { return e1.compareTo(e2) < 0; } diff --git a/module5/src/main/java/com/hithomelabs/princeton1/module5/Insertion.java b/module5/src/main/java/com/hithomelabs/princeton1/module5/Insertion.java index 49ce313..c6faf70 100644 --- a/module5/src/main/java/com/hithomelabs/princeton1/module5/Insertion.java +++ b/module5/src/main/java/com/hithomelabs/princeton1/module5/Insertion.java @@ -1,23 +1,15 @@ 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; - } + @Override + public void sort(E[] arr) { + for(int i=1; i=0 && less((Comparable) arr[k], arr[j]); j--){ + exch(arr, k, j); + k = j; } } - - } - - } +} diff --git a/module5/src/main/java/com/hithomelabs/princeton1/module5/Selection.java b/module5/src/main/java/com/hithomelabs/princeton1/module5/Selection.java index 3b0a0c1..4f8c1ff 100644 --- a/module5/src/main/java/com/hithomelabs/princeton1/module5/Selection.java +++ b/module5/src/main/java/com/hithomelabs/princeton1/module5/Selection.java @@ -1,23 +1,20 @@ package com.hithomelabs.princeton1.module5; - +/* + * * 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 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++){ + @Override + public void sort(E[] arr) { + for (int i = 0; i < arr.length; i++) { int minIndex = i; - for(int j = i+1; j < arr.length; j ++){ - if (less((Comparable) arr[j], arr[minIndex])) minIndex = j; + 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 index d253056..7d26813 100644 --- a/module5/src/main/java/com/hithomelabs/princeton1/module5/Shell.java +++ b/module5/src/main/java/com/hithomelabs/princeton1/module5/Shell.java @@ -25,32 +25,37 @@ public class Shell extends AbstractCustomSorts { @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(3*h + 1 < arr.length){ + h = 3*h + 1; } - while (h >= 1) { - h = hsort(arr, h, metaData); - h = h / 3; + while(h>=1){ + hsort(arr, h, metaData); + h= h/3; } +// for(int i=arr.length/10; i>=0; i--){ +// hsort(arr, 3*i+1, metaData); +// } 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; + private void hsort(E[] arr, int h, MetaData metadata) { + for(int i=h; i=0; j=j-h){ + metadata.compares++; + if(less((Comparable) arr[k], arr[j])){ + exch(arr, k, j); + k = j; + metadata.swaps++; + } + else{ + break; + } + } } - return h; } /* * Sample implementation of insertion sort as h-sort of h = 1 @@ -59,7 +64,7 @@ public class Shell extends AbstractCustomSorts { public void insertionSort(E[] arr){ MetaData metaData = new MetaData(); int h = 1; - h = hsort(arr, h, metaData); + hsort(arr, h, metaData); System.out.println("Array sorted (insertion sort) with " + metaData.compares + " compares and " + metaData.swaps + " swaps"); } diff --git a/module6/src/main/java/com/hithomelabs/princeton1/module6/Merge.java b/module6/src/main/java/com/hithomelabs/princeton1/module6/Merge.java index 5cffa56..b541cb8 100644 --- a/module6/src/main/java/com/hithomelabs/princeton1/module6/Merge.java +++ b/module6/src/main/java/com/hithomelabs/princeton1/module6/Merge.java @@ -5,40 +5,40 @@ import com.hithomelabs.princeton1.module5.AbstractCustomSorts; import java.util.Arrays; public class Merge extends AbstractCustomSorts { + private E[] auxArr; + @Override public void sort(E[] arr) { - - int N = arr.length; - // * * aux is a helper array required for merge - E[] aux = Arrays.copyOf(arr, N); - mergesort(arr, aux, 0, N-1); - + auxArr = (E[]) new Object[arr.length]; + merge_sort(arr, 0, arr.length-1); } - private void mergesort(E[] arr, E[] aux, int lo, int hi) { + private void merge_sort(E[] arr, int low_index, int high_index){ + if(high_index - low_index > 0) { + int mid_index = low_index + (high_index - low_index)/2; + merge_sort(arr, low_index, mid_index); + merge_sort(arr, mid_index + 1, high_index); - if (hi <= lo) return; - int mid = lo + (hi - lo)/2; - mergesort(arr, aux, lo, mid); - mergesort(arr, aux, mid+1, hi); - merge(arr, aux, lo, mid, hi); + // Copy array + for(int i=low_index; i<= high_index; i++) + auxArr[i] = arr[i]; - } - - private void merge(E[] arr, E[] aux, int lo, int mid, int hi) { - - // * * creating backup of original array - for (int i = lo; i <= hi; i++) - aux[i] = arr[i]; - - int i = lo; - int j = mid+1; - for (int k = lo; k <= hi; k++){ - // * If i has already reached mid, no need to compare we insert at pointer k - if(i > mid) arr[k] = aux[j++]; - else if(j > hi) arr[k] = aux[i++]; - else if(less((Comparable) aux[i], aux[j])) arr[k] = aux[i++]; - else arr[k] = aux[j++]; + // Sort + int low_index_ptr = low_index; + int mid_index_ptr = low_index + (high_index - low_index)/2; + int high_index_ptr = mid_index_ptr + 1; + if(!less((Comparable) auxArr[mid_index_ptr], auxArr[high_index_ptr])) { + for (int i = low_index; i <= high_index; i++) { + if (low_index_ptr > mid_index_ptr) { + arr[i] = auxArr[high_index_ptr++]; + } else if (high_index_ptr > high_index) + arr[i] = auxArr[low_index_ptr++]; + else if (less((Comparable) auxArr[low_index_ptr], auxArr[high_index_ptr])) + arr[i] = auxArr[low_index_ptr++]; + else + arr[i] = auxArr[high_index_ptr++]; + } + } } } } diff --git a/module7/src/main/java/com/hithomelabs/princeton1/module7/Quick.java b/module7/src/main/java/com/hithomelabs/princeton1/module7/Quick.java index c3e4c40..0f69460 100644 --- a/module7/src/main/java/com/hithomelabs/princeton1/module7/Quick.java +++ b/module7/src/main/java/com/hithomelabs/princeton1/module7/Quick.java @@ -6,49 +6,45 @@ import com.hithomelabs.princeton1.module5.AbstractCustomSorts; public class Quick extends AbstractCustomSorts { @Override public void sort(E[] arr) { - int N = arr.length; - quickSort(arr, 0, N - 1); + randomShuffle(arr); + partition(arr, 0, arr.length-1); } - public void altSort(E[] arr) { - int N = arr.length; - altQuickSort(arr, 0, N-1); + private void randomShuffle(E[] arr){ + int array_len = arr.length; + for(int i=0; i< array_len; i++){ + int random_index = (int)(Math.random()*array_len); + exch(arr, i, random_index); + } } - private void altQuickSort(E[] arr, int lo, int hi) { - if (lo >= hi) return; - int i = lo + 1; - int j = i; - while(j <= hi){ - if(less((Comparable) arr[j], arr[lo])){ - exch(arr, i, j); + private void partition(E[] arr, int low, int high){ + if(low >= high) + return; + int mid = sort(arr, low, high); + partition(arr, low, mid-1); + partition(arr, mid + 1, high); + } + + private int sort(E[] arr, int low, int high){ + int i = low+1; + int j = high; + while (true){ + // Find the i index greater than 1st element + while (i<=high && !less((Comparable) arr[low], arr[i])) i++; - } - j++; + // Find the j index less than 1st element + while (less((Comparable) arr[low], arr[j]) && j > low) + j--; + // Break if indexes are crossed + if(j < i) + break; + // Swap index values of i & j + if(less((Comparable) arr[j], arr[i])) + exch(arr, i, j); } - exch(arr, i-1, lo); - altQuickSort(arr, lo, i-2); - altQuickSort(arr, i, hi); - } - - private void quickSort(E[] arr, int lo, int hi) { - - if (lo >= hi) return; - int i = lo; - int j = hi+1; - while(true){ - while(less((Comparable) arr[++i], arr[lo])){ - if(i == hi) break; - } - while(!less((Comparable) arr[--j], arr[lo])){ - if (j == lo ) break; - } - if(j<=i) break; - exch(arr, i , j); - } - exch(arr, j, lo); - quickSort(arr, lo, j-1); - quickSort(arr, j+1, hi); - + // Swap 1st element to it's correct position + exch(arr, low, j); + return j; } } diff --git a/module7/src/test/java/com/hithomelabs/princeton1/module7/QuickTest.java b/module7/src/test/java/com/hithomelabs/princeton1/module7/QuickTest.java index e252c68..3ff75b9 100644 --- a/module7/src/test/java/com/hithomelabs/princeton1/module7/QuickTest.java +++ b/module7/src/test/java/com/hithomelabs/princeton1/module7/QuickTest.java @@ -33,6 +33,8 @@ class QuickTest { Assertions.assertArrayEquals(sorted, arr); } + // * * Optional test for alternate sort implmentation + /* @Test @DisplayName("testing Quick sort default implementation") public void testAltSort(){ @@ -45,6 +47,8 @@ class QuickTest { Apple[] sorted = apples.toArray(new Apple[apples.size()]); Assertions.assertArrayEquals(sorted, arr); } + */ + @AfterEach