Data Structures and Software Principle - Exam 2 | CS 225, Study notes of Data Structures and Algorithms

Material Type: Notes; Class: Data Structures; Subject: Computer Science; University: University of Illinois - Urbana-Champaign; Term: Fall 2005;

Typology: Study notes

Pre 2010

Uploaded on 03/16/2009

koofers-user-wo0-1
koofers-user-wo0-1 🇺🇸

10 documents

1 / 12

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
University of Illinois at Urbana-Champaign
Department of Computer Science
Second Examination
CS 225 Data Structures and Software Principles
Fall 2005
7:00pm 8:15pm Monday, October 24
Name: SOLUTIONS
NetID:
Lab Section (Day/Time):
This is a closed book and closed notes exam. No electronic aids are allowed, either.
You should have 6 sheets total (the cover sheet, plus numbered pages 1-11). The last sheet is
scratch paper; you may detach it while taking the exam, but must turn it in with the exam
when you leave. The second-to-last page contains some class and function declarations you
have seen before; you can use this sheet as reference while taking the exam.
Unless otherwise stated in a problem, assume the best possible design of a particular imple-
mentation is being used.
Unless the problem specifically says otherwise, (1) assume the code compiles, and thus any
compiler error is an exam typo (though hopefully there are not any typos), and (2) assume
you are NOT allowed to write any helper methods to help solve the problem, nor are you
allowed to use additional arrays, lists, or other collection data structures unless we have said
you can.
Problem Points Score Grader
1 15
2 15
3 15
4 15
5 15
6 15
Total 90
pf3
pf4
pf5
pf8
pf9
pfa

Partial preview of the text

Download Data Structures and Software Principle - Exam 2 | CS 225 and more Study notes Data Structures and Algorithms in PDF only on Docsity!

University of Illinois at Urbana-Champaign

Department of Computer Science

Second Examination

CS 225 Data Structures and Software Principles

Fall 2005

7:00pm – 8:15pm Monday, October 24

Name: SOLUTIONS

NetID:

Lab Section (Day/Time):

  • This is a closed book and closed notes exam. No electronic aids are allowed, either.
  • You should have 6 sheets total (the cover sheet, plus numbered pages 1-11). The last sheet is scratch paper; you may detach it while taking the exam, but must turn it in with the exam when you leave. The second-to-last page contains some class and function declarations you have seen before; you can use this sheet as reference while taking the exam.
  • Unless otherwise stated in a problem, assume the best possible design of a particular imple- mentation is being used.
  • Unless the problem specifically says otherwise, (1) assume the code compiles, and thus any compiler error is an exam typo (though hopefully there are not any typos), and (2) assume you are NOT allowed to write any helper methods to help solve the problem, nor are you allowed to use additional arrays, lists, or other collection data structures unless we have said you can.

Problem Points Score Grader

Total 90

  1. [Analysis – 15 points].

You have objects of type Foo (the particulars of type Foo don’t matter for this problem, aside from the fact that the <, == and > operators are defined for this type). You are storing copies of these objects in two different data structures – a sorted doubly-linked list and a binary search tree. If you’ve already inserted n objects into your collection (each time you insert a Foo object into the collection, you are inserting it into both the binary search tree and the sorted doubly-linked list) then what is the average case running time for inserting an additional object into your collection (i.e. inserting that object into each of the two structures)? Express your answer in big-O notation and justify your answer.

An insert into a sorted list is basically a search-and-insert, since you need to search for where the value goes before you can insert it. For a sorted linked list, searching will be O(n), and then the actual insertion is O(1), so total, a sorted insert is O(n), whether average case or worst case. A binary search tree insertion is O(lg n) in the average case. So, if you want the time it takes to insert into both structures together, you just add the times for the two individual insertions. “Time for sorted insert into sorted linked list in average case” plus “time to insert into binary search tree in average case” is O(n) + O(lg n) = O(n).

  1. [TreeTraversals – 15 points].

Your task is to complete the function everyOtherLevel, which has one parameter – a pointer of type BinaryTreeNode (the BinaryTreeNode class appears on page 8), which points either to NULL or to the root node of a binary tree. You want to perform a level order traversal on the tree, but only on every other level – i.e. level 0 (which is the level the root node is on), level 2 (which is two levels below the root), level 4 , and so on. Or in other words, it’s a level order traversal where you completely ignore the odd levels. You are allowed to use one Queue in your solution; that Queue would have only the four standard ADT functions, the Big Three, and a no-argument constructor that initialized the Queue to be empty.

void everyOtherLevel(TreeNode* root) { // your code goes here

Queue<TreeNode> Q; Q.enqueue(root); while (!Q.isEmpty()) { TreeNode temp = Q.dequeue(); if (temp != NULL) { cout << temp->element << endl; if (temp->left != NULL) { Q.enqueue(temp->left->left); Q.enqueue(temp->left->right); }

if (temp->right != NULL) { Q.enqueue(temp->right->left); Q.enqueue(temp->right->right); } } } }

  1. [Ordered Trees – 15 points].

Your task is to complete the function fourthToFirst, which has one parameter – a pointer of type OrderedTreeNode (the OrderedTreeNode class appears on page 8), which points either to NULL or to the root node of an ordered tree (this tree could be a subtree of a larger ordered tree), implemented using the binary tree implementation of an ordered tree (as you dealt with on MP6). For any nodes in the tree that have at least four children, you want to move the fourth child to be the first child (meaning the former first child becomes the second child, the former second child becomes the third child, and the former third child becomes the fourth child). You are not allowed to change the integer element in any node; you need to manipulate pointers to accomplish this task.

void fourthToFirst(OrderedTreeNode* root) { // your code goes here

TreeNode* trav = root->firstChild; if ((trav != NULL) && (trav->nextSibling != NULL) && (trav->nextSibling->nextSibling != NULL) { // trav points to third node after this line trav = trav->nextSibling->nextSibling;

if (trav->nextSibling != NULL) { TreeNode* fourth = trav->nextSibling; trav->nextSibling = trav->nextSibling->nextSibling; fourth->nextSibling = root->firstChild; root->firstChild = fourth; } }

trav = root->firstChild; while (trav != NULL) { fourthToFirst(trav); trav = trav->nextSibling; } }

(Lists, continued)

ListNode* minFive(ListNode* head) { ListNode* skipTrav = head; while (skipTrav != NULL) { ListNode* minPtr = skipTrav; ListNode* fiveTrav = skipTrav; for (int i = 2; i <= 5; ++i) { fiveTrav = fiveTrav->next; if (fiveTrav->element < minPtr->element) minPtr = fiveTrav; }

// now move fiveTrav one more node, to point to start of next five fiveTrav = fiveTrav->next;

if (minPtr != skipTrav) { // extract min if (minPtr->next != NULL) minPtr->next->prev = minPtr->prev; minPtr->prev->next = minPtr->next;

// insert min before skipTrav minPtr->next = skipTrav; minPtr->prev = skipTrav->prev; if (skipTrav->prev == NULL) head = minPtr; else skipTrav->prev->next = minPtr; skipTrav->prev = minPtr; }

skipTrav = fiveTrav; } return head; }

  1. [Patricia Trees – 15 points].

Your task is to complete the function busiestNode, which has one parameter, a pointer of type PatriciaNode (the PatriciaNode class appears on page 8), which is either NULL, or points to the root node of a Patricia tree or subtree of a Patricia tree. You want to return an integer. Specifically, you want to find the “array node” (i.e. non-leaf node) in the tree which points to the maximum number of other array nodes, and return the number of array nodes that node actually points to. Or in other words, find the node that has the most number of pointers that aren’t pointers to leaf nodes or NULL, and return how many such pointers that node has.

int busiestNode(PatriciaNode* nodePtr) { // your code goes here

int total = 0; for (int i = (nodePtr->ptrArray).lower(); nodePtr->ptrArray).upper(); i++) { if ((nodePtr->ptrArray)[i] != NULL) && (!(nodePtr->ptrArray)[i]->isLeaf))) total++: }

int max = total; for (int i = (nodePtr->ptrArray).lower(); nodePtr->ptrArray).upper(); i++) { if ((nodePtr->ptrArray)[i] != NULL) { int result = busiestNode((nodePtr->ptrArray)[i]); if (result > total) max = result } } return max; }

This is info regarding the Array class and String class used by the PatriciaNode class on the previous page.

class String // here are the member function declarations for the String class String(); // initializes to empty string String(char const * initString); // initializes to "literal" parameter String(String const & origVal); // copy constructor ~String(); // destructor String const & operator=(String const & origVal); // assignment op char operator[](int index) const; // accesses char at parameter index char & operator[](int index); // accesses char at parameter index String substring(int startIndex, int substringLength) const; // piece of this beginning at startIndex; substringLength chars long String concat(String const & secondString) const; // appends param to copy // of this String int length() const; // length of string // we’ve left the six relational operators (operator==, operator<, // etc.) out; you don’t need them. friend std::ostream & operator<<(std::ostream & Out, String const & outputString); // prints

template class Array // Here are the member function declarations for the Array class; // we’ve left the declarations for the iterators and iterator // support functions (begin(), end(), etc.) out; you don’t need them. Array(); // size 0 array, indiced 0 through - Array(int low, int high); // indices low through high Array(Array const & origVal); // copy constructor ~Array(); // destructor Array const & operator=(Array const & origVal);//assignment op Etype const & operator[](int index) const; // accesses cell at param index

Etype & operator[](int index); // accesses cell at param index void initialize(Etype const & initElement); // inits all cells to param void setBounds(int theLow, int theHigh); // changes bounds of array, int size() const; // returns number of cells in array int lower() const; // returns lowest index int upper() const; // returns upper index

(scratch paper, page 1)