Exercises A#
Note
You must complete these exercises by Wednesday of W2.
Abstract Data Types: Interface vs. Class#
Define what an abstract data type (ADT) is. In Java, is it better to describe an ADT by a class or an interface? Why?
Stack at the End of a Singly Linked List#
How would you implement a stack using a singly linked list where the push and pop operations are done at the end of the list? Is this solution efficient? Justify your answer.
Stack Implementations and java.util.Stack#
What are the possible implementations for a stack? By consulting the Java API documentation, describe
the implementation of a stack by the class java.util.Stack. Go to the source code of the implementation
java.util.Stack (Ctrl+B from IntelliJ).
Why do you think Java developers chose this implementation (hint: argue about memory and garbage collection)?
Implement a Stack with Two Queues#
How do you implement the abstract data type stack using two queues?
In particular, describe how the push and pop methods work in this case.
As an example, specify the state of each of the two queues after pushing the integers 1 2 3 onto an initially empty stack.
Describe what happens next when the pop operation is performed.
What is the time complexity of these methods if we assume that each enqueue and dequeue
operation is executed in constant time?
Is this implementation of a stack efficient (for \(n\) operations) compared to the other implementations presented in the reference book?
Once you have imagined your solution on paper, you can solve the corresponding INGInious task StackWithTwoQueues.
Iterating Over a LinkedList vs. ArrayList#
What do you think about these three different ways of iterating over the elements of a java.util.LinkedList? Are they equivalent? Use a time-complexity argument.
Does replacing new LinkedList<>() with new ArrayList<>() on the first line change the performance of these loops?
List<Integer> list = new LinkedList<>();
// assume I insert n elements in the list here
for (Integer val: list) {
System.out.println(val);
}
Iterator<Integer> itr = list.iterator();
while (itr.hasNext()) {
Integer val = itr.next();
System.out.println(val);
}
for (int i = 0; i < list.size(); i++) {
Integer val = list.get(i);
System.out.println(val);
}
Asymptotic Notations: Tilde vs. Big-Oh, Omega, Theta#
The \(\sim\) (tilde) notation is used in the reference book for the analysis of the running times of algorithms. How does this notation differ from or resemble the more commonly used notations \(\mathcal{O}\) (big Oh), \(\mathcal{\Omega}\) (big Omega), and \(\mathcal{\Theta}\) (big Theta)?
Explain precisely the links and similarities between them. What do you see as the advantage of using the \(\sim\) (tilde) notation rather than \(\mathcal{O}\) when possible?
The Doubling Ratio Test#
Explain how we can extract the \(\sim\) (tilde) characterization from the implementation of an algorithm using the doubling ratio test.
How does this test work?
What are the limitations and advantages of this test?
Suppose we measure the following \(T(n)\) execution times (in seconds) of a program as a function of the input size \(n\):
\(n\) |
1000 |
2000 |
4000 |
8000 |
16000 |
32000 |
64000 |
\(T(n)\) |
0 |
0 |
0.1 |
0.3 |
1.3 |
5.1 |
20.5 |
How can you best characterize the growth order of this function?
What would be the running time for 128000?
JVM Memory: Stack, Heap, and Garbage Collector#
What do heap and stack represent when talking about the execution of a program?
What do the
-Xmxand-Xmsparameters mean when running Java bytecode on the JVM?Can these parameters influence the execution speed of a Java program? Why?
What is the JVM garbage collector?
Unit Testing, Edge Cases, and Complexity Verification#
What is a good set of unit tests to verify the correctness of a data structure?
Do you think about edge cases?
What could possibly go wrong with this method implementation?
// return the floor of the average between a and b
public static int average(int a, int b) {
return (a + b) / 2;
}
How can random data generation be useful for testing data structures?
Why is it important to work with a fixed seed for testing?
How can a code coverage analysis tool (such as JaCoCo) help you design tests?
How can you verify experimentally that the implementation of a data structure or an algorithm has the expected theoretical time complexity?
How can you test the time complexity of your program?
SegmentedList and Iterators#
You are asked to implement an ADT called a SegmentedList and the iterator method of this ADT: SegmentedList.