Skip to content

Latest commit

 

History

History
100 lines (73 loc) · 5.56 KB

ex02.md

File metadata and controls

100 lines (73 loc) · 5.56 KB

Exercise 02

The goal of this exercise is to give you experience in implementing the data structures mentioned in the lecture and allow a better understanding of such structures. In addition The exercise shows how, in addition to the basic functionality, some data structures may implement functionality that is specific to them.

Allowing an ArrayList, for example, to be resizable (see Part A) allows for such structures to be more useful and usable.

As an overview:

  • you will implement your code in a class that extends (in this case) MyArrayList. This means that you will have to override the appropriate methods (in this case add(int index, T value)) in a way that addresses the requirements in the task.
  • the task has some tests associated with it, that test said functionality. These tests assume that you implemented the functionality correctly and in the appropriate method.
  • To access the tests, you will have to write an appropriate test class that extends (in this case) the class MyListTestTemplate. This includes a number of tests that assess the behaviours of lists.
  • there is an override you need to do in your test class, in order to ensure the correct behaviour.
  • NOTE that all the parts that ask you to create implementations of list also use the same test template: MyListTestTemplate. The different parts will require different implementations and will have the appropriate details. But they all have to fulfill the basic functionality of a List, and that is what the test template assesses.

Part A

Write a class called MyArrayListResizable that extends MyArrayList.

Override the method add(int index, T value) in a way that, if the internal array is full, then such array should be doubled in size before inserting the new element.

Write a test class called MyArrayListResizableTest that extends MyListTestTemplate, where the instance of MyArrayListResizable is initialized with capacity of 1 (i.e., the size for the internal array). If your implementation of MyArrayListResizable#add is correct, then all tests should pass.

Part B

Using MyLinkedList as a starting point, create a new class called MyBidirectionalLinkedList. Here, besides a next link, each node also has a previous link pointing to the previous node in the list. All insert/delete operations need to properly handle and update such previous links. When inserting/deleting/getting a node at position index, the algorithm should decide if rather start the search from head using next links, or from tail using the previous links. If index <= size()/2, it makes sense to start from head. On the other hand, when index > size()/2 it would be more efficient to start from tail.

Write a MyBidirectionalLinkedListTest that extends MyListTestTemplate. If your implementation is correct, all tests should pass.

Part C

Write a new class MyMiddleBidirectionalLinkedList that extends MyList, using MyBidirectionalLinkedList as starting point. However, besides having a link to the head and the tail of the list, you need to have a 3rd link, pointing to the middle of the list. When you need to access an element (e.g., with a get), then you need to minimize the number of nodes to traverse. For example, assume a list with 100 elements, and you need to delete the element at position 40. Then, the most efficient way would be to start from the middle link, and go backwards following the previous links till position 40. On the other hand, if accessing at position 20, it would be more efficient to start from head and follow the next links. In other words, all indices in the range 25%-75% of the size of the list should be accessed starting from the middle link.

Pay particular attention at the fact that, at each delete and add operation, the value of middle will likely need to be updated. Note: in case of list with an even number of elements, the middle could have 2 values, choose the lower. For example: length=1 and length=2 would have middle at position 0, whereas length=3 and length=4 would have it at position 1, length=5 at 2, and so on.

Write a MyMiddleBidirectionalLinkedListTest that extends MyListTestTemplate. If your implementation is correct, all tests should pass.

Part D

Write a class called MyRingArrayQueue that implements MyQueue. Internally, it should be similar to the implementation of MyQueueArray, but with a fundamental performance improvement. When by adding many elements the tail index reaches the end of the internal array, instead of shifting elements to the left or copying over to a new larger array, the tail should start back from 0, unless of course head==0.

The idea is to reuse the empty spaces before head when head>0. Note, when head==0, or when tail increases so much that it reaches head, then it would mean that the array is completely full, and you need to copy over to a new internal array.

Write a MyRingArrayQueueTest that extends MyQueueTestTemplate. If your implementation is correct, all tests should pass. Run the tests with code coverage enabled, and verify that all of the instructions in your code are covered. If not, add new tests to MyRingArrayQueueTest.

Part E

Study the source code of MyLinkedList, MyStackLinkedList and MyQueueArray. Once you think you fully understand them, write their implementation on paper (e.g., using a pen), without looking at the source code. Once done, compare what you wrote with the actual implementations.

Solutions

Solutions to this exercise can be found in the solutions module, under the org.pg4200.sol02 package.