kruti-working-branch #14
@ -6,23 +6,11 @@ import javax.annotation.Nonnull;
|
||||
|
||||
public class ArrayQueue<E> extends Queue<E>{
|
||||
|
||||
// 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<E> extends Queue<E>{
|
||||
|
||||
@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<E> extends Queue<E>{
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public Iterator<E> iterator() {
|
||||
return new Iterator<E>() {
|
||||
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<size; i++)
|
||||
hitanshu marked this conversation as resolved
Outdated
|
||||
queueArray[j++]=tempArray[(startPtr+i)%oldArraySize];
|
||||
endPtr = size();
|
||||
startPtr = 0;
|
||||
queueArrayLength = queueArray.length;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Iterator<E> iterator() {
|
||||
return new QueueArrayIterator();
|
||||
}
|
||||
|
||||
private class QueueArrayIterator implements Iterator<E>{
|
||||
|
||||
private int iteratorIndex = startPtr;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return iteratorIndex % queueArrayLength < endPtr % queueArrayLength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E next() {
|
||||
hitanshu marked this conversation as resolved
hitanshu
commented
Iterator does not account for wrapping Iterator does not account for wrapping
|
||||
return queueArray[iteratorIndex++ % queueArrayLength];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,93 +6,68 @@ import javax.annotation.Nonnull;
|
||||
// Creating a generic stack of type E
|
||||
public class ArrayStack<E> extends Stack<E> {
|
||||
|
||||
// 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<E> iterator() {
|
||||
return new Iterator<E>() {
|
||||
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<E>{
|
||||
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++];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,70 +5,76 @@ import java.util.Iterator;
|
||||
|
||||
public class LinkedQueue<E> extends Queue<E>{
|
||||
|
||||
Node head;
|
||||
Node tail;
|
||||
int size;
|
||||
Node<E> start = null;
|
||||
Node<E> end = null;
|
||||
|
||||
private class Node{
|
||||
E value;
|
||||
Node next;
|
||||
static private class Node<E>{
|
||||
E data;
|
||||
Node<E> 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;
|
||||
hitanshu marked this conversation as resolved
Outdated
hitanshu
commented
Case where only 1 element in queue, end pointer is dangling. Case where only 1 element in queue, end pointer is dangling.
|
||||
return currentValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enqueue(E element) {
|
||||
Node newNode = new Node(element);
|
||||
Node<E> new_node = new Node<E>(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<E> sizePtr = start;
|
||||
while (sizePtr != null) {
|
||||
sizePtr = sizePtr.next;
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
@Override
|
||||
public Iterator<E> iterator() {
|
||||
return new Iterator<E>() {
|
||||
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<E>{
|
||||
|
||||
Node<E> traversePtr = start;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return traversePtr != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E next() {
|
||||
E currentValue = traversePtr.data;
|
||||
traversePtr = traversePtr.next;
|
||||
return currentValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<E> extends Stack<E>{
|
||||
|
||||
// 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>{
|
||||
E data;
|
||||
Node<E> 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<E> head = null;
|
||||
hitanshu marked this conversation as resolved
hitanshu
commented
Why do you need two pointers, both insertion and deletion happen at head Why do you need two pointers, both insertion and deletion happen at head
|
||||
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<E> new_node = new Node<E>(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<E> iterator() {
|
||||
return new Iterator<E>() {
|
||||
|
||||
// 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<E>{
|
||||
|
||||
Node<E> iteratorPtr = head;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return iteratorPtr.next != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E next() {
|
||||
E currentValue = iteratorPtr.data;
|
||||
iteratorPtr = iteratorPtr.next;
|
||||
return currentValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,12 +4,14 @@ public abstract class AbstractCustomSorts<E> {
|
||||
|
||||
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<E> e1, E e2) {
|
||||
return e1.compareTo(e2) < 0;
|
||||
}
|
||||
|
@ -1,23 +1,15 @@
|
||||
package com.hithomelabs.princeton1.module5;
|
||||
|
||||
public class Insertion<E> extends AbstractCustomSorts<E> {
|
||||
|
||||
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<E>)arr[j], arr[j-1])){
|
||||
exch(arr, j, j-1);
|
||||
j = j-1;
|
||||
}
|
||||
@Override
|
||||
public void sort(E[] arr) {
|
||||
for(int i=1; i<arr.length; i++){
|
||||
int k = i;
|
||||
for(int j=i-1; j>=0 && less((Comparable<E>) arr[k], arr[j]); j--){
|
||||
exch(arr, k, j);
|
||||
k = j;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<E> extends AbstractCustomSorts<E>{
|
||||
|
||||
/*
|
||||
* * 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<E>[] arr1 = (Comparable<E>[]) 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<E>) arr[j], arr[minIndex])) minIndex = j;
|
||||
for(int j = i+1; j < arr.length; j++){
|
||||
if(less((Comparable<E>) arr[j], arr[minIndex]))
|
||||
minIndex = j;
|
||||
}
|
||||
exch(arr, i, minIndex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -25,32 +25,37 @@ public class Shell<E> extends AbstractCustomSorts<E> {
|
||||
@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<E>) 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<arr.length; i=i+1){
|
||||
int k = i;
|
||||
for(int j=i-h; j>=0; j=j-h){
|
||||
metadata.compares++;
|
||||
if(less((Comparable<E>) 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<E> extends AbstractCustomSorts<E> {
|
||||
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");
|
||||
}
|
||||
|
||||
|
@ -5,40 +5,40 @@ import com.hithomelabs.princeton1.module5.AbstractCustomSorts;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class Merge<E> extends AbstractCustomSorts<E> {
|
||||
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);
|
||||
hitanshu marked this conversation as resolved
Outdated
hitanshu
commented
Making a new aux arry with each recursive call is expensive Making a new aux arry with each recursive call is expensive
|
||||
|
||||
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<E>) 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<E>) 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<E>) auxArr[low_index_ptr], auxArr[high_index_ptr]))
|
||||
arr[i] = auxArr[low_index_ptr++];
|
||||
else
|
||||
arr[i] = auxArr[high_index_ptr++];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,49 +6,45 @@ import com.hithomelabs.princeton1.module5.AbstractCustomSorts;
|
||||
public class Quick<E> extends AbstractCustomSorts<E> {
|
||||
@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<E>) 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<E>) arr[low], arr[i]))
|
||||
i++;
|
||||
}
|
||||
j++;
|
||||
// Find the j index less than 1st element
|
||||
while (less((Comparable<E>) 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<E>) 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<E>) arr[++i], arr[lo])){
|
||||
if(i == hi) break;
|
||||
}
|
||||
while(!less((Comparable<E>) 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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user
If the old queue is wrapped, then endPtr will be less than startPtr