diff --git a/.gitea/workflows/gradle_build.yml b/.gitea/workflows/gradle_build.yml new file mode 100644 index 0000000..f135547 --- /dev/null +++ b/.gitea/workflows/gradle_build.yml @@ -0,0 +1,24 @@ +name: sample gradle build and test +run-name: Build started by $ {{gitea.actor }} +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Check out repository code + uses: actions/checkout@v4 + - name: JDK setup + uses: actions/setup-java@v4 + with: + distribution: 'zulu' + java-version: '21' + - name: Validate Gradle Wrapper + uses: gradle/actions/wrapper-validation@v3 + - name: Gradle build + run: ./gradlew build -i + diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/clients/src/main/java/com/hithomelabs/clients/ArrayQueueClient.java b/clients/src/main/java/com/hithomelabs/clients/ArrayQueueClient.java new file mode 100644 index 0000000..7022367 --- /dev/null +++ b/clients/src/main/java/com/hithomelabs/clients/ArrayQueueClient.java @@ -0,0 +1,20 @@ +package com.hithomelabs.clients; + +import com.hithomelabs.princeton1.module4.ArrayQueue; +import com.hithomelabs.princeton1.module4.Queue; + +public class ArrayQueueClient { + public static void main(String[] args) { + Queue queue = new ArrayQueue(); + for(int i = 0; i < 21; i++){ + queue.enqueue(i); + } + for(int i = 0; i < 13; i++){ + System.out.println(queue.dequeue()); + } + + // Using object s, as stack is generic but every java Object has implementation of toString() + for (Object s : queue) + System.out.println(s); + } + } diff --git a/clients/src/main/java/com/hithomelabs/clients/ArrayStackClient.java b/clients/src/main/java/com/hithomelabs/clients/ArrayStackClient.java new file mode 100644 index 0000000..53a40c1 --- /dev/null +++ b/clients/src/main/java/com/hithomelabs/clients/ArrayStackClient.java @@ -0,0 +1,19 @@ +package com.hithomelabs.clients; + +import com.hithomelabs.princeton1.module4.ArrayStack; +import com.hithomelabs.princeton1.module4.Stack; + +public class ArrayStackClient { + public static void main(String[] args) { + Stack stack = new ArrayStack(); + for(int i = 0; i < 21; i++){ + stack.push(i); + } + // Using object s, as stack is generic but every java Object has implementation of toString() + for (Object s : stack) + System.out.println(s); + while(!stack.isEmpty()){ + System.out.println(stack.pop()); + } + } +} diff --git a/clients/src/main/java/com/hithomelabs/clients/LinkedQueueClient.java b/clients/src/main/java/com/hithomelabs/clients/LinkedQueueClient.java new file mode 100644 index 0000000..008742c --- /dev/null +++ b/clients/src/main/java/com/hithomelabs/clients/LinkedQueueClient.java @@ -0,0 +1,20 @@ +package com.hithomelabs.clients; + +import com.hithomelabs.princeton1.module4.LinkedQueue; +import com.hithomelabs.princeton1.module4.Queue; + +public class LinkedQueueClient { + public static void main(String[] args) { + Queue queue = new LinkedQueue(); + for(int i = 0; i < 21; i++){ + queue.enqueue(i); + } + for(int i = 0; i < 13; i++){ + System.out.println(queue.dequeue()); + } + + // Using object s, as stack is generic but every java Object has implementation of toString() + for (Object s : queue) + System.out.println(s); + } + } diff --git a/clients/src/main/java/com/hithomelabs/clients/Main.java b/clients/src/main/java/com/hithomelabs/clients/LinkedStackClient.java similarity index 95% rename from clients/src/main/java/com/hithomelabs/clients/Main.java rename to clients/src/main/java/com/hithomelabs/clients/LinkedStackClient.java index d8c5d68..33cc4e9 100644 --- a/clients/src/main/java/com/hithomelabs/clients/Main.java +++ b/clients/src/main/java/com/hithomelabs/clients/LinkedStackClient.java @@ -4,7 +4,7 @@ package com.hithomelabs.clients; import com.hithomelabs.princeton1.module4.LinkedStack; import com.hithomelabs.princeton1.module4.Stack; -public class Main { +public class LinkedStackClient { public static void main(String[] args) { Stack stack = new LinkedStack(); stack.push("hello"); diff --git a/module4/src/main/java/com/hithomelabs/princeton1/module4/ArrayQueue.java b/module4/src/main/java/com/hithomelabs/princeton1/module4/ArrayQueue.java new file mode 100644 index 0000000..4e8988e --- /dev/null +++ b/module4/src/main/java/com/hithomelabs/princeton1/module4/ArrayQueue.java @@ -0,0 +1,103 @@ +package com.hithomelabs.princeton1.module4; + +import javax.annotation.Nonnull; +import java.util.Iterator; + +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 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; + } + + @Override + public boolean isEmpty() { + return size == 0; + } + + @Override + public E dequeue() { + 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; + } + } + + @Override + public void enqueue(E element) { + // We plan capacity expansion if needed + if (size == capacity){ + capacity = capacity * 2; + resize(capacity, capacity/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 + public int size() { + return size; + } + + @Override + @Nonnull + public Iterator iterator() { + return new Iterator() { + int counter = size; + int pointer = head; + @Override + public boolean hasNext() { + return counter != 0; + } + + @Override + public E next() { + E element = arr[pointer]; + pointer = (pointer + 1)% capacity; + --counter; + return element; + } + }; + } +} diff --git a/module4/src/main/java/com/hithomelabs/princeton1/module4/ArrayStack.java b/module4/src/main/java/com/hithomelabs/princeton1/module4/ArrayStack.java new file mode 100644 index 0000000..0ae2eb6 --- /dev/null +++ b/module4/src/main/java/com/hithomelabs/princeton1/module4/ArrayStack.java @@ -0,0 +1,98 @@ +package com.hithomelabs.princeton1.module4; +import javax.annotation.Nonnull; +import java.util.Iterator; + +// 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 + 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 parametrised constructor with default initial capacity 10 + public ArrayStack(){ + this(DEFAULT_CAPACITY); + } + + @Override + public boolean isEmpty() { + return size == 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; + } + + @Override + public E pop() { + if (isEmpty()) + return null; + else{ + E e = arr[--size]; + arr[size] = null; + checkResize(); + return e; + } + } + + private void checkResize() { + if (size < capacity / 4 && capacity >= 40){ + capacity = capacity / 2; + changeCapacity(capacity); + } + } + + @Override + public int size() { + return size; + } + + @Override + @Nonnull + public Iterator iterator() { + return new Iterator() { + + int current = 0; + + @Override + public boolean hasNext() { + return current != size; + } + + @Override + public E next() { + E element = arr[current]; + current = current + 1; + return element; + } + }; + } +} diff --git a/module4/src/main/java/com/hithomelabs/princeton1/module4/LinkedQueue.java b/module4/src/main/java/com/hithomelabs/princeton1/module4/LinkedQueue.java new file mode 100644 index 0000000..ec37bbe --- /dev/null +++ b/module4/src/main/java/com/hithomelabs/princeton1/module4/LinkedQueue.java @@ -0,0 +1,74 @@ +package com.hithomelabs.princeton1.module4; + +import javax.annotation.Nonnull; +import java.util.Iterator; + +public class LinkedQueue extends Queue{ + + Node head; + Node tail; + int size; + + private class Node{ + E value; + Node next; + + Node(E value){ + this.value = value; + } + } + + @Override + public boolean isEmpty() { + return size==0; + } + + @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; + } + + @Override + public void enqueue(E element) { + Node newNode = new Node(element); + if(isEmpty()) + head = newNode; + else + tail.next = newNode; + tail = newNode; + ++size; + } + + @Override + public int size() { + return size; + } + + @Override + @Nonnull + public Iterator iterator() { + return new Iterator() { + Node current = head; + @Override + public boolean hasNext() { + return current != tail; + } + + @Override + public E next() { + E element = current.value; + current = current.next; + return element; + } + }; + } +} diff --git a/module4/src/main/java/com/hithomelabs/princeton1/module4/Queue.java b/module4/src/main/java/com/hithomelabs/princeton1/module4/Queue.java new file mode 100644 index 0000000..6c4999d --- /dev/null +++ b/module4/src/main/java/com/hithomelabs/princeton1/module4/Queue.java @@ -0,0 +1,10 @@ +package com.hithomelabs.princeton1.module4; + +public abstract class Queue implements Iterable { + + public abstract boolean isEmpty(); + public abstract E dequeue(); + public abstract void enqueue(E element); + public abstract int size(); +} +