1) Consider a Sorted Doubly-Linked List, which means that keys are kept always sorted and stored in a doubly linked list:
a) Implement an operation SD-LIST-INSERT(L,k) that inserts an integer key k into list L. What is the running time Θ(.) of your implementation?
b) Implement an operation SD-LIST-DELETE(L,k) that removes a key k from the list. What is the running time Θ(.) of your implementation?
c) Implement operations SD-LIST-SUCCESSOR(L,k) and SD-LIST-PREDECESSOR(L,k) that returns the successor and predecessor of a key k, respectively. What is the running time Θ(.) of your implementation?
d) Implement an operation SD-LIST-SEARCH(L,k) that searches for a key k in list L and returns its node position (e.g., 1 if first, 2 if second, etc). What is the running time Θ(.) of your implementation?
e) Implement an operation SD-LIST-REVERSE(L) that reverses the order of the keys in place (i.e., Θ(n) space complexity). What is the running time Θ(.) of your implementation?
2) Consider inserting 15 distinct letters into a Hash Table of size m=9 using open-addressing with auxiliary function h'(k)=position_in_alphabet(k). For example, h'(A)=1, h'(B)=2, h'(C)=2, etc.
a) Choose 15 unique letters to be your keys.
Then, illustrate the result of inserting these keys in the order defined in a) using:
b) Linear probing;
c) Quadratic probing with c1=1 and c2=3;
d) Double hashing with h1(k)=h'(k) and h2(k)=1+(h'(k) mod (m-1))
Show your calculations.
3) Consider an application that frequently inserts data into a BST and even more frequently performs searches on these data. Because of the high demand for search operations, this application simply can't afford the worst-case searches of a BST (i.e., Θ(n)). To this end, it frequently has to check the height of the BST so it can rebalance it if necessary. It is your chance to show your value to the company and improve their application.
Your first job is:
a) To implement an operation called TREE-HEIGHT(x) that (efficiently) calculates the height h of a node x in the BST of Chapter 12 (i.e., h=#levels-1);
b) Next, answer what the time and space complexity of your implementation is;
After a few tests though, you realize that your time complexity is still too high for the application. Therefore, you decide to approach the problem from a different perspective. You decide to add an extra field to each node in the BST that stores the height of that node in the tree. That should allow you to look up the tree height in constant time.
So your second job is:
c) To make all necessary changes to TREE-INSERT(T,z) and TREE-DELETE(T,z) to accommodate an extra field for the height of each node;
d) To implement another operation called TREE-HEIGHT-LOOKUP(x) that retrieves the height h of the node x in constant time;
Now, your third and final job is:
e) To evaluate and discuss your 2 approaches by answering: "Which of the 2 applications is more efficient? The one with TREE-HEIGHT(x) or the one with TREE-HEIGHT-LOOKUP(x)?" Explain.
*Tip: Note that by allowing constant time height look-ups, you added some overhead in computing 2 other operations.