LMU ☀️ CMSI 2120
DATA STRUCTURES
HOMEWORK #2 Due: 2022-10-06

Learning Objectives

With this assignment you will demonstrate:

Readings and Videos

Please:

Instructions

Work in teams of 1 to 2 students.

Your work will be done in a private GitHub repository called lmu-cmsi-2120 or something similar. Submit to BrightSpace a single text file or pdf that contains the link to this repo. Submit only one submission per team.

Structure your repository, for now, as follows:

  .
  ├── README.md
  ├── .gitignore
  ├── homework1/
  │   └── (existing files from previous assignments)
  └── homework2/
      ├── README.md                      (Include ALL students’ names)
      ├── Stack.java                     (from the course notes)
      ├── StackTest.java                 (from the course notes)
      ├── Queue.java                     (from the course notes)
      ├── QueueTest.java                 (from the course notes)
      ├── ExpandableArrayStack.java      (write this)
      └── ExpandableArrayQueue.java      (write this)
      ├── ExpandableArrayStackTest.java  (given to you below)
      └── ExpandableArrayQueueTest.java  (given to you below)

When grading, I will clone your repository, and run the test program. Since the repo is to be private, please add me as a contributor to your repo (so I can run and comment on your work). My github name is rtoal.

You will be graded on your programming style, so make sure you are set up so that your editor or IDE auto-formats your code. You should also install Sonar Lint because it is amazing. Environment set up was carried out in class earlier, so you should be good already.

Your homework submission will be the state of your repository on the branch master, at 23:59 in the America/Los Angeles time zone on the due date above.

Make sure your README has the names of all the students that have worked on the project.

The Classes You Are To Write

In class we’ve seen stack and queue interfaces and implementations for each using bounded arrays and linked structures. We’ve see unit tests as well.

In this assignment you are to add two new classes: one a stack implementation using an expandable array (that must implement the Stack interface from class), and one a queue implementation using an expandable array (that must implement the Queue interface from class).

The work is less involved than it seems. You have already seen the mechanics of adding and removing to stacks and queues. All that you are “adding” to the mix is the growing and shrinking of the backing array, as well as the necessary copying. You will be developing a sense for low-level code and how data structure implementation affects the time and space complexity of your programs. You will be gaining further Java practice, too!

The rules to follow are:

Here’s the tester for your new stack class:

ExpandableArrayStackTest.java
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.BeforeEach;
import static org.junit.jupiter.api.Assertions.assertEquals;

public class ExpandableArrayStackTest extends StackTest {

    @BeforeEach
    public void makeExpandableArrayStack() {
        s = new ExpandableArrayStack();
    }

    @Test
    public void testPushToFullStackGrowsTheStack() {
        int initialCapacity = ((ExpandableArrayStack) s).capacity();
        for (var i = 0; i < initialCapacity; i++) {
            assertEquals(initialCapacity, ((ExpandableArrayStack) s).capacity());
            s.push("abc");
        }
        assertEquals(s.size(), ((ExpandableArrayStack) s).capacity());
        s.push(Math.PI);
        assertEquals(s.size(), initialCapacity + 1);
        assertEquals(initialCapacity * 2, ((ExpandableArrayStack) s).capacity());
        while (s.size() < initialCapacity * 2) {
            assertEquals(initialCapacity * 2, ((ExpandableArrayStack) s).capacity());
            s.push("abc");
        }
        assertEquals(initialCapacity * 2, ((ExpandableArrayStack) s).capacity());
        s.push("abc");
        assertEquals(initialCapacity * 4, ((ExpandableArrayStack) s).capacity());
    }

    @Test
    public void testStackGetsSmallerWhenTooSparse() {
        int initialCapacity = ((ExpandableArrayStack) s).capacity();
        for (var i = 0; i < initialCapacity * 4; i++) {
            s.push("abc");
        }
        s.push("abc");
        assertEquals(initialCapacity * 4 + 1, s.size());
        assertEquals(initialCapacity * 8, ((ExpandableArrayStack) s).capacity());
        s.pop();
        assertEquals(initialCapacity * 4, s.size());
        assertEquals(initialCapacity * 8, ((ExpandableArrayStack) s).capacity());
        for (var i = 0; i < initialCapacity * 2; i++) {
            s.pop();
        }
        assertEquals(initialCapacity * 2, s.size());
        assertEquals(initialCapacity * 8, ((ExpandableArrayStack) s).capacity());
        s.pop();
        assertEquals(initialCapacity * 2 - 1, s.size());
        assertEquals(initialCapacity * 4, ((ExpandableArrayStack) s).capacity());
    }

    @Test
    public void testStackDoesNotShrinkWhenCapacityAtMinium() {
        int initialCapacity = ((ExpandableArrayStack) s).capacity();
        for (var i = 0; i < initialCapacity; i++) {
            s.push("abc");
            assertEquals(initialCapacity, ((ExpandableArrayStack) s).capacity());
        }
        for (var i = 0; i < initialCapacity; i++) {
            s.pop();
            assertEquals(initialCapacity, ((ExpandableArrayStack) s).capacity());
        }
    }
}

Here’s the tester for your new queue class:

ExpandableArrayQueueTest.java
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.BeforeEach;
import static org.junit.jupiter.api.Assertions.assertEquals;

public class ExpandableArrayQueueTest extends QueueTest {

    @BeforeEach
    public void makeExpandableArrayQueue() {
        q = new ExpandableArrayQueue();
    }

    @Test
    public void testenqueueToFullQueueGrowsTheQueue() {
        int initialCapacity = ((ExpandableArrayQueue) q).capacity();
        for (var i = 0; i < initialCapacity; i++) {
            assertEquals(initialCapacity, ((ExpandableArrayQueue) q).capacity());
            q.enqueue("abc");
        }
        assertEquals(q.size(), ((ExpandableArrayQueue) q).capacity());
        q.enqueue(Math.PI);
        assertEquals(q.size(), initialCapacity + 1);
        assertEquals(initialCapacity * 2, ((ExpandableArrayQueue) q).capacity());
        while (q.size() < initialCapacity * 2) {
            assertEquals(initialCapacity * 2, ((ExpandableArrayQueue) q).capacity());
            q.enqueue("abc");
        }
        assertEquals(initialCapacity * 2, ((ExpandableArrayQueue) q).capacity());
        q.enqueue("abc");
        assertEquals(initialCapacity * 4, ((ExpandableArrayQueue) q).capacity());
    }

    @Test
    public void testQueueGetsSmallerWhenTooSparse() {
        int initialCapacity = ((ExpandableArrayQueue) q).capacity();
        for (var i = 0; i < initialCapacity * 4; i++) {
            q.enqueue("abc");
        }
        q.enqueue("abc");
        assertEquals(initialCapacity * 4 + 1, q.size());
        assertEquals(initialCapacity * 8, ((ExpandableArrayQueue) q).capacity());
        q.dequeue();
        assertEquals(initialCapacity * 4, q.size());
        assertEquals(initialCapacity * 8, ((ExpandableArrayQueue) q).capacity());
        for (var i = 0; i < initialCapacity * 2; i++) {
            q.dequeue();
        }
        assertEquals(initialCapacity * 2, q.size());
        assertEquals(initialCapacity * 8, ((ExpandableArrayQueue) q).capacity());
        q.dequeue();
        assertEquals(initialCapacity * 2 - 1, q.size());
        assertEquals(initialCapacity * 4, ((ExpandableArrayQueue) q).capacity());
    }

    @Test
    public void testQueueDoesNotShrinkWhenCapacityAtMinium() {
        int initialCapacity = ((ExpandableArrayQueue) q).capacity();
        for (var i = 0; i < initialCapacity; i++) {
            q.enqueue("abc");
            assertEquals(initialCapacity, ((ExpandableArrayQueue) q).capacity());
        }
        for (var i = 0; i < initialCapacity; i++) {
            q.dequeue();
            assertEquals(initialCapacity, ((ExpandableArrayQueue) q).capacity());
        }
    }
}

Grading

As before, the following elements will all contribute to your grade:

In addition, I will be scoring code quality, which is sometimes subjective to be sure, but you deserve feedback.