Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
COMP1406 - Winter 2014 - Tutorial 10 1: Recursive Data Structures - Linked Lists Linked lists are discussed in §8.9 and §9.2 of the course notes. A linked list is one way in which we implement the list abstract data type. Recall that a list is a collection of data that has a sequential (linear) order. That is, there is a first element, a second element, . . . , and a last element. The LinkedList class from the notes is actually a doubly-linked list. The class only directly “sees” (has an attribute for) two of the items in the list: the first item and the last item. public class LinkedList{ Node head; Node tail; private int size; ... } // first element in the list // last element in the list // number of elements in the list Each element in the list is stored in a node (or item class from the notes) and each node is linked (has a reference to) two other nodes. Since linked lists are sequential containers (the data being stored has a linear order just like in an array), we say that each node is linked to the previous node and also to the next node. For simplicity, we’ll assume that the elements in the list will be stored as a String object. public class Node{ String data; Node next; Node previous; } For example, a linked list with three nodes (with data "cat", "dog" and "eel", in that order) can be visualize as follows: 1 è Download the LinkedList and Node classes from the tutorial webpage. Look at this class and make sure you understand how the add(Node), toString(), and most importantly, the toStringHelper(Node) methods work. The toStringHelper method is a recursive private helper method to generate a string representation of nodes linked together. To help you work with linked lists and help you test your code, use the toString() method to help you keep track of the current state of the linked list (by printing out its contents in the proper order). Thinking about Linked Lists è Consider the following snippet of code. Node n1 = new Node("panthro"); Node n2 = new Node("lion-o"); Node n3 = new Node("jaga"); Node n4 = new Node("cheetara"); Node n5 = new Node("tygra"); Node n6 = new Node("wilykit"); n2.next = n4; n3.next = n1; n5.next = n3; n5.next.next.next = n6; n6.next = n2; Draw a memory model of the state of the computer after this code is run. (You should draw a picture like the one drawn on the previous page. Note that none of the previous references are defined. è What commands are needed to make the sequence of Node objects (from above) a LinkedList object? Which nodes are the head and tail nodes? Linked List Functionality è Write a boolean method find(String) that returns true if the input string is in the linked list and false if not. Your solution must use recursion. Just as toString() uses the recursive toStringHelper(Node) as a helper method, you will want to write a helper method, findHelper(String, Node), to perform the actual recursion. For example, outputs list.toString() −−−−→ <A, B, C, D, E> outputs list.find("F") −−−−→ false outputs list.find("E") −−−−→ true 2 è Since the LinbkedList class uses a doubly-linbked list, we should be able to move through the list both forwards and backwards. Write a method toStringReverse() that returns a string (just as toString()), but with the elements in reverse order. Again, you must use recursion for this. You will want a recursive helper method toStringReverseHelper(Node). For example, outputs list.toString() −−−−→ <A, B, C, D, E> outputs list.toStringReverse() −−−−→ <E, D, C, B, A> è Write a method called addBack(Node) that adds a node to the back of the linked list. This method should not be recursive and it should not use iteration. It should be very similar to the add(Node) method provided. For example, outputs list.toString() −−−−→ <A, B, C, D, E> outputs list.addBack("end") −−−−→ <A, B, C, D, E, end> outputs list.addBack("E") −−−−→ <A, B, C, D, E, end, E> è Write a method called add(Node newNode, int position) that inserts a node into a linked list at a specified position. The position zero is the front/start of the list. If a negative position is entered, it should add the element at position zero. If the position exceeds the size of the linked list it should simply add to the back/end of the list. You must use recursion for this problem. Again, use a recursive helper method. For example, suppose list is a LinkedList object with 3 elements currently in it. outputs list.toString() −−−−→ <A, B, C> outputs list.add( new Node("q"), 0) −−−−→ <q, A, B, C> outputs list.add( new Node("dog"), 2) −−−−→ <q, A, dog, B, C> outputs list.add( new Node("end"), 15) −−−−→ <q, A, B, C, end> outputs list.add( new Node("wind"), 4) −−−−→ <q, A, B, C, wind, end> è Write a method called remove(int) that removes the node at the specified position and returns the data (the String) that is in that node. Again, position zero is the front/start of the list. If a negative position is entered, the first node should be removed from the list and its string returned by the method. If the position exceeds the size of the linked list it should simply remove the last element in the list and return its string. You must use recursion for this problem. Again, use a recursive helper method. 3 For example, suppose list is a LinkedList object with 5 elements currently in it. outputs list.toString() −−−−→ <A, B, C, D, E> outputs list.remove(1) −−−−→ "B" outputs list.toString() −−−−→ <A, C, D, E> outputs list.remove(1) −−−−→ "C" outputs list.toString() −−−−→ <A, D, E> outputs list.remove(12) −−−−→ "E" outputs list.toString() −−−−→ <A, D> Extra Work on these problems for extra practice working with recursion and linked lists. Each of your solutions should involve recursion. è Write a static method stringToLinkedList(String), that takes a string, in the format of the output of the toString() method, and returns a linked list object based on the string. For example, list = stringToLinkedList("<A, B, C, D, E>") outputs list.toString() −−−−→ <A, B, C, D, E> è Write a boolean method doubles() that checks if any two consecutive nodes in the current linked list store the same string (data). The method should return true if there are two such nodes satisfy this and false otherwise. For example, list = stringToLinkedList("<A, B, C, D, E>") outputs list.doubles() −−−−→ false list.add(new Node("B", 7)) outputs list.toString() −−−−→ <A, B, C, D, E, B> outputs list.doubles() −−−−→ true è Write a static method merge(LinkedList, LinkedList) that takes as input two sorted linked list object. That is, the nodes in each input linked list has data (strings) that are in alphabetical (sorted) order. The method will create a new linked list object that consists of all the data in both input lists in sorted order. 4 For example, listA = stringToLinkedList("<A, D, Q, R>") listB = stringToLinkedList("<B, C, F, P, R, W, Y, Z>") listMerged = merge(listA, listB) outputs listMerged.toString() −−−−→ <A, B, C, D, F, P, Q, R, R, W, Y, Z> è Assume that all strings (data attributes) are single character strings. Write a static method isPalindrome(LinkedList) that returns true of the ordering of the characters in the input list are a valid palindrome and false otherwise. Use recursion to solve this problem. Recall that a sequence of characters is a palindrome if and only if the sequence read forward is the same the sequence read backwards. For example, list = stringToLinkedList("<W, O, r, r, O, W>") outputs isPalindrome(list) −−−−→ true list.add("A") outputs isPalindrome(list) −−−−→ false è Write a function insert(LinkedList, int) that inserts the input list into the current linked list at the position specified. For example, outer = stringToLinkedList("<a, b, c, d, e, f>") inner = stringToLinkedList("<cat, dog, eel>") outer.insert(inner, 2) outputs outer.toString() −−−−→ <a, b, cat, dog, eel, c, e, f> outer.insert(inner, 3) outputs outer.toString() −−−−→ <a, b, cat, cat, dog, eel, dog, eel, c, e, f> 5 Extra Extra For this problem we will consider a singly-linked list. This is just the linked list we have been using already, except that each node has no previous attribute. For our purposes, we’ll just let previous = null for each node. We’ll also let tail = null. è Write a static method called hasCycle(LinkedList) that determines if the input list has a cycle in it. For example, the following linked list has a loop. If this linked list was named list, hasCycle(list) should return true. If you tried to visit each node in this linked list (using recursion or iteration) you would keep visiting the last two nodes indefinitely until your program had stack overflow error (recursion) or it you terminated the program since it was taking too long (iterative approach). Note that the toString() method will not work properly with a single linked list because it uses tail. Note: This is a common interview question. It is worthwhile learning how to solve this. More Recursion If you are looking for more practice with recursive data structures, try working out the binary tree problems found here: Tutorial Questions (Java Files) 6