CS 171: Introduction to Computer Science II Assignment #4: Playlist Application and Sorting
Hello, dear friend, you can consult us at any time if you have any questions, add WeChat: daixieit
CS 171: Introduction to Computer Science II
Assignment #4: Playlist Application and Sorting
Due: Sunday, July 30th at 11:59 PM ET on Gradescope [Late submission: see syllabus]
Problem Description: We are interested in developing a Playlist application that supports adding, deleting, and even sorting podcast episodes (alphabetically). To make navigating our Playlist flexible, we looked for a data structure that supports dynamic adding and removing of episodes, while also supporting easy and smooth traversing back and forth between episodes.
For these reasons, we will be using a Doubly Linked List to implement our Playlist, where each episode is represented as a node. Recall that each node in a doubly linked list has two links, one that refers to the next node and another that refers to the previous node. For our Playlist, this design choice means it will be easy to move forward or backward from any episode!
The starter code includes three Java classes:
(1) Class Episode represents an individual podcast episode. You can think of it as the equivalent of a ‘Node’ class in our lecture examples, but with more fields and methods. Each episode has a title, length (duration), a link to the next episode, and a link to the previous episode. Additionally, class Episode implements the Java interface Comparable, which enables comparing two episodes using the method compareTo. Please do not modify or add anything to this class.
(2) Class Playlist represents a doubly linked list of Episode objects. The playlist has two instance variables: the head (i.e. the first episode in the list), and a size integer (i.e. the total number of episodes so far). You will implement all the operations supported in this Playlist by filling the code for its member methods. Remember to always make sure that the Playlist’s head and size variables are updated properly for each operation (e.g., the size is incremented by 1 if a new node is added, etc.). The file Playlist.java is the only file you must submit to Gradescope.
(3) Finally, class ITunes represents the application that will test the different features supported in your Playlist. You can modify the code in this class as you wish, to test and debug your Playlist implementation.
Note that the Playlist may contain no episodes (e.g. when it is first created), a single episode, or multiple episodes. The figure below shows how the nodes should be linked if there are multiple episodes in the list. Pay attention to how next and prev are wired. Also, note that de-referencing links in your code more than once is possible; so episodeObject.prev.next is valid (assuming episodeObject is an object of type Episode).
Part 1: Playlist Operations
Below is a summary of the methods in class Playlist relevant to Part 1 of this assignment. Some are already implemented (you can use them for testing and debugging), and others are up to you to implement:
. [Implemented] String toString(): Our overriding of toString() prints the Playlist’s episodes starting at the first (head) episode and ending at the last episode.
. [Implemented] String toReverseString(): This method prints the Playlist’s episodes backwards, starting at the last episode and ending at the first (head) episode. It utilizes the prev reference in each node to be able to move backwards.
. [Implemented] int getSize() returns the value of the size variable, and boolean isEmpty() returns true if the list is empty.
. [13 points] TODO: void addFirst(String title, double duration): Create a new Episode using the given title and duration parameters, then add this Episode properly at the beginning of the current Playlist.
. [13 points] TODO: void addLast(String title, double duration): Create a new Episode using the given title and duration parameters, then add this Episode properly at the end of the current Playlist.
. [15 points] TODO: Episode deleteFirst(): This method should properly delete andre-turn the first Episode in the playlist. If the list is empty, it should throw a NoSuchElementException().
. [16 points] TODO: Episode deleteLast(): This method should properly delete and re-turn the last Episode in the playlist. If the list is empty, it should throw a NoSuchElementException().
. [16 points] TODO: Episode deleteEpisode(String title): This method should prop- erly delete and return the Episode with the given title. If the list is empty or the episode title is not found, it should throw a NoSuchElementException().
Part 2: Sorting the Playlist
What if the playlist user is interested in having all the episodes sorted alphabetically on their app? To provide this cool feature, you will implement a sorting algorithm for our playlist. But which algorithm should we use? For sorting linked lists, mergesort is often preferred since it can be implemented with O(1) extra space, and since random-access algorithms like quicksort perform poorly on linked lists.
In the starter-code, we provided a partial implementation of mergesort for the Playlist, which is missing the merge() operation only. Your job is to provide the implementation of merge (without creating any auxiliary data structures!). Note that both splitting and merging nodes in a linked list is done by re-linking the nodes’ prev and next references properly, without the need for creating an additional data structure to copy the elements back and forth (like we did for regular arrays in our lecture’s mergesort examples).
Here is a summary of the sorting methods in class Playlist:
. [Implemented] Episode getMiddleEpisode(Episode node): Since mergesort requires re- peated splits of the list into two halves, we provided this helper method that identifies the middle node in the list by defining two pointers to traverse the list: a slow pointer that hops one node at a time, and a fast pointer hops two nodes at a time. When fast reaches the end of the list, slow will be about half way. Elegant, eh?
. [Implemented] Episode sort(Episode node): Similar to our mergesort class example, this method splits the playlist recursively into two halves, and then calls the method merge that you will implement to merge the two sublists. The parameter node is a reference to the beginning of the list to be sorted.
. [22 points] TODO: Episode merge(Episode a, Episode b): This is the only method you need to implement. It is responsible for merging two sorted lists into one sorted list. You can approach this problem iteratively or recursively (your choice!). Your implementation must use the method compareTo(), available in class Episode, whenever you need to compare two Episode objects. Tip: There are several cases to deal with when merging two lists: either list could be empty, you may run out of elements in ‘left’ first, ‘right’ first, and so on.
Getting Started and Debugging Tips
. Download the starter code on Canvas and understand it: Episode.java, Playlist.java, and ITunes.java.
. Start by solving the add and delete methods in class Playlist. Test your code incrementally and work on one method at a time. In class ITunes, you can test and debug each method by printing the list using both toString() and toReverseString(), to ensure that nodes are linked properly in both directions (via next and prev references).
. Then, move on to the sorting methods. Read the given methods very carefully and think about how the merge operation should be designed. Test your logic on a small concrete example first (on paper), then debug and test your implementation in class ITunes.
. Test your methods on different scenarios; e.g., an empty list, a list with one node, multiple
nodes, deleting a node from different positions in the list, etc.
. The only file you will submit on Gradescope is Playlist.java.
Grading
. If your program does not compile, you will get 0 points from the autograded portion.
. Playlist operations are properly implemented with correct logic and exception handling: 73 points
. Playlist mergesort correctly sorts the episodes in alphabetical order and is implemented effi-ciently (does not time-out on Gradescope): 22 points
. Code clarity, style, and comments: 5 points
Honor Code
The assignment is governed by the College Honor Code and Departmental Policy. Remember, any code you submit must be your own; otherwise you risk being investigated by the Honor Council and facing the consequences of that. We do check for code plagiarism (across student submissions and against online resources). Please remember to have the following comment included at the top of the file.
/* THIS CODE WAS MY OWN WORK, IT WAS WRITTEN WITHOUT CONSULTING CODE WRITTEN BY OTHER STUDENTS OR ONLINE RESOURCES .
_Student_Name_Here_ */
Submission Checklist: We’ve created this checklist to help you make sure you don’t miss anything important. Note that completing all these items does not guarantee full points, but at least assures you are unlikely to get a zero.
□ Did your file compile on the command line using JDK 11 or above (e.g. JDK 17)?
□ Did your submission on Gradescope successfully compile and pass at least one autograder test case?
□ Have you included the honor code on top of the file?
□ Did you remove the TODO prefix from the methods you needed to implement?
□ Did you give your variables meaningful names (i.e., no foo or bar variables)?
□ Did you add meaningful comments to the code when appropriate?
2023-07-31