Final Exam Review: Part 2 - CS2
37. Implement the body of the following function using a binary search of the array. You do not need to check the precondition. All your local variables must be size_t variables. bool has_42(const int data[ ], size_t n) // Precondition: The elements data[0]...data[n-1] are sorted from // smallest to largest. The value of n might be zero (indicating an // empty array). // Postcondition: A true return value indicates that the number 42 // appears in data[0]...data[n-1]. A false return value indicates // that 42 doesn't appear.
bool has_42(const int data[ ], size_t n) { size_t middle = n/2; if (n == 0) // Empty array cannot contain 42. return false; else if (data[middle] == 42) // We found the number 42. return true; else if (data[middle] > 42) // Continue search of data[0]...data[middle-1]. return has_42(data, middle); else // Continue search of data[middle+1]...data[n-1]. return has_42(data+(middle+1), n-(middle+1)); }
I plan to put 1000 items in a hash table, and I want the average number of accesses in a successful search to be about 2.0. A. About how big should the array be if I use open addressing with linear probing? NOTE: For a load factor of A, the average number of accesses is generally ½(1+1/(1-A)). B. About how big should the array be if I use chained hashing? NOTE: For a load factor of A, the average number of accesses is generally (1+A/2).
A. Start by solving for A in the equation 2 = 0.5(1+1/(1-A)). This gives a load factor of A = 2/3. To obtain this load factor with 1000 items, the table size must be 1500. B. Start by solving for A in the equation 2 = 1+A/2. This gives a load factor of A = 2. To obtain this load factor with 1000 items, the table's size must be 500
List an application that will benefit from the use of the binary search tree and justify your answer.
All the problems that search for an element can benefit of a binary search tree. However we must remember that in a binary search tree the elements are stored in order and the order must be maintained after further insertions or deletions
Give a concise accurate description of a good way for quicksort to choose a pivot element. Your approach should be better than "use the entry at location [0]".
Choose three random items from the array. Use the middle of these three items for the pivot.
Describe all the possible cases that can occur when deleting a node from a binary search tree
Deleting a leaf is simple. The leaf is simply removed. If we delete a node with one child, we can move its child in its place. The most complex case is when we remove a node with both children. In that case we find its successor (resp. its predecessor) which is the leftmost (resp. the rightmost) leaf of its right subtree (resp. left subtree) and we replace it with that node
What are the advantages of hashing over performing a binary search?
Hashing can be faster in the average case. Adding and deleting elements is easier in containers that provide hashing, because binary search requires that items remain sorted.
When is it appropriate to use a container class of pointers to objects (rather than a container class of actual objects)?
If the container class functions provide mere copies of the objects and the program needs to store and manipulate the actual objects themselves, then it would be appropriate to use a container class of pointers to objects.
Suppose a hash table is full and you try to insert a new entry on the table. What happens if the new entry's key is already in the table? What happens if the new entry's table is not already in the table?
If the key was already present, then the record is overwritten. If the key was not already present, then the program detects that the table is full and it halts or it sends an error message or it communicate that there is no space in the table where the record can be added.
Here is an array of ten integers: 5 3 8 9 1 7 0 2 6 4 Draw this array after the FIRST iteration of the large loop in a selection sort (sorting from smallest to largest).
If the selection sort is selecting the largest item first then the array will be 5 3 8 4 1 7 0 2 6 9 Another way to run a selection sort is to find the smallest item first. Then the array will be 0 3 8 9 1 7 5 2 6 4
Is this statement correct? If not, correct it. depth(leaf node) = 1 + depth(left subtree), depth(right subtree)
No it is incorrect. The depth of a leaf node is one more than the depth of its parent node. If we talk about the depth of a tree, the formula is still incorrect since you should not add both the depth of the left and right subtree but just pick whichever is the largest, i.e. depth(tree) = 1 + max{depth(left subtree), depth(right subtree)} Remember that the depth of a tree with just a root node is 0.
Consider the following binary tree. A / \ B C / D Is the tree complete? Justify our answer.
No the tree is not complete. A complete binary tree has all the level filled from the left to the right. To be complete D had to be the left child of B.
Describe a case where quicksort will result in quadratic behavior.
Quicksort has quadratic behavior when each partition is bad (for example, one side of the partition has no elements and the other side has everything except the pivot).
How do we insert an element in a binary search tree?
Starting from the root we visit the binary search tree by moving to the left if the element to insert is smaller than the visited node or to the right if the element to insert is larger than the visited node. We continue until we reach a leaf. At this point the element is inserted either to the left or to the right of that leaf according to the value of the element (smaller-left, larger-right).
Suppose that a derived class has a private base class. How is it possible to make some of the inherited members become public?
The name of the inherited member is listed in the public section of the derived class.
Here is an array which has just been partitioned by the first step of quicksort: 3, 0, 2, 4, 5, 8, 7, 6, 9 Which of these elements could be the pivot? (There may be more than one possibility!)
The pivot must be the 4, the 5, or the 9.
What is the difference between polymorphism and overloading?
The word "Polymorhpism" comes from the Greek meaning "having multiple forms". It is the characteristic of being able to assign a different meaning or usage to something in different contexts. A variable or a function with a given name may be allowed to have different forms and the program can determine which form of the variable or of the function to use at the time of execution. In overloading the same symbol is used to implement different operators. Function overloading is accomplished by using the same function name but changing the argument list. In both cases the program can determine which operator or function to use before execution time.
Suppose that you implement quicksort nonrecursively using a stack, as in your last programming assignment. You use your algorithm to sort an array of 100 items, and at the start of the final iteration of the while loop, the stack contains just two numbers: 10 (on top) and 90 (on bottom). Write one or two clear sentences to describe which parts of the array are sorted at this point, and which parts of the array remain to be sorted
There is an unsorted section of 10 elements beginning at index [90]. The rest of the array is already sorted.
Describe one purpose of a member initialization list for a derived class.
To call a constructor for the base class
If the programmer doesn't declare any constructors for a derived class, an automatic default constructor will be provided by the compiler. What steps will this default constructor carry out?
(1) Activate the default copy constructor for the base class, and (2) Activate default copy constructors for any new member variables that the derived class has but the base class does not have
If the programmer doesn't declare a destructor for a derived class, an automatic destructor will be provided by the compiler. What steps will this destructor carry out?
(1). Activate the destructor for any new member variables that the derived class has but the base class does not have, and (2). Activate the destructor for the base class.
Write one or two sentences to describe the primary advantage of implementing a derived class. Your answer should use the word "inherited" at least once.
A derived class inherits the member functions of the base class, without having to reimplement these functions.
Here is an array with exactly 15 elements: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Suppose that we are doing a serial search for an element. Circle any elements that will be found by examining two or fewer numbers from the array.
Assuming that the serial search starts at the front of the array, 1 and 2 are the only two numbers that can be found by examining two or fewer numbers.
In which situation a function is defined virtual?
We define virtual function when the choice of which version of the function must be used is made during the execution of the program. Pure virtual functions are used in base classes when we want to defer their implementation to their derived classes.
Give a concise accurate description of a good way for quicksort to improve its performance by using insertion sort.
When the array to sort is small, quicksort can just call insertion sort to do its work (instead of partitioning and making recursive calls).
Describe the difference between a public base class and a private base class.
With a public base class, all of the public members of the base class become public members of the derived class. With a private base class, all of the public members of the base class become private members of the derived class.
What do you have to guarantee when you remove an element from a hash table?
You must guarantee that the element is marked as "previously used". If this is not done, future searches in the table will not perform correctly.
Suppose that you are writing a program that has these two functions available: int compare_ints(const void* p1, const void* p2); // Precondition: p1 and p2 are really pointers to integers. // Postcondition: The return value is: // (a) negative if *p1 < *p2 // (b) zero if *p1 == *p2 // (c) positive if *p1 > *p2 void qsort( void* base, size_t n, size_t bytes, int compar(const void*, const void*)); // Same specification as the standard library qsort function. Your program also has an integer array called x, with 10 elements. Write two function calls: The first call uses qsort to sort all of x; the second call uses qsort to sort x[3]..x[9].
qsort(x, 10, sizeof(int), compare_ints); qsort(x+3, 7, sizeof(int), compare_ints);