Sunteți pe pagina 1din 2

Data Structure & Algorithms

CS210A,ESO207A,ESO211
Semester I, 2012-13, CSE, IIT Kanpur
Programming Assignment III
Deadline : midnight of 9th October for the rst and second problem and midnight of
18th October for the third problem
Note: This programming assignment consists of three problems. You will have to design modules
to generate random input instances for each of these problems and test your algorithms on these inputs.
You will have to bring a one or two page report at the time of demo/viva for each of these problems.
1 Divide and Conquer algorithm for multiplying integers
Let x and y be any two binary numbers consisting of n bits each. The trivial algorithm to multi-
ply these numbers takes O(n
2
) time. We discussed a divide and conquer based algorithm which takes
O(n
log
2
3
) = O(n
1.59
) time. You have to implement these two algorithms and compare their performance
experimentally. More specically, you have to achieve the following objectives.
Verify whether the experimentally observed running time of each algorithm matches its theoretical
time complexity. For this purpose, you will have to run your algorithms multiple times on suciently
large range of input instances. Instead of plotting running time T(n) versus n, would it be better
if we plot log(T(n)) versus log n ?
What steps will you take in this experiment to verify whether you have implemented the two
algorithms correctly ?
For implementation of each of these algorithms, nd out the largest value of n such that two numbers
of n bits can be multiplied in 1 minute, 10 minutes.
What useful lessons do you learn from this experimentation ?
2 Quick sort: the most preferred sorting algorithm in practice!
We all know that the worst case time complexity of quick sort is O(n
2
). But, quick sort is still the most
preferred sorting algorithm in practice. It outperforms your favourite merge sort algorithm in real life
applications. Also note that unlike merge sort which requires O(n) extra space, quick sort requires only
O(1) extra space. We shall prove in some lecture that average running time of quick sort is O(nlog n).
Here average running time means the time complexity of quick sort averaged over all n! permutations.
Interestingly, what makes quick sort practically the most ecient sorting algorithm is not just its average
running time. In fact, as the input size increases, it becomes more likely that its running time is going
to be around O(nlog n) only. Is it not amazing ? In order to get a theoretical explanation of such a
wonderful behavior, do a course on randomized algorithm.
You have to implement quick sort and merge sort and compare their performance on suciently large
input instances generated randomly and uniformly. For quick sort, you have to demonstrate experi-
mentally that its running time becomes more and more concentrated aroud O(nlog n) as the value of n
increases.
1
3 Randomized Binary Search Trees
We know that a binary search tree is eective only if its height is of logarithmic order of its size. The
researchers have devised various height balanced trees for this purpose: AVL tree, red-black tree. However,
the algorithms to maintain these trees as height balanced are quite complex. Secondly, they have extra
overhead of space: they require extra bit(s) to be stored in each node. On the other hand, it is too easy
to implement various operations on an ordinary binary search tree. But we also know that the worst case
height of an ordinary binary search tree can be as bad as O(n). However, in real life, such worst case
might not occur. There are many applications where the elements to be inserted or deleted follow some
probability distribution. Theorefore, if the keys to be inserted are generated randomly uniformly, does it
make sense to keep an ordinary binary search tree instead of red-black tree or AVL tree? Your aim is to
get answer to this question experimentally.
Implement binary search tree to support each of the following operations on a given set S (which is
empty initially):
1. Insert(S, x): Insert x into the set S.
2. Search(S, x): Determine if x is present in S.
3. Min(S): Report the minimum element from S.
4. Max(S): Report the maximum element from S.
5. Predecessor(S, x): Report the largest element from S which is smaller than x (return -1 if no such
element exists).
6. Successor(S, x): Report the smallest element from S which is greater than x (return -1 if no such
element exists).
You have to rst insert n elements generated randomly and unoformly from a suitable range (think
over it). This has to be followed by a random sequence of 10n operations mentioned above. You have to
compute the following values experimentally:
the maximum time taken by each of these operations.
the average time taken by each operation.
the height of the tree at the end of these operations.
How do these values vary as a function of n (or log n) ? Make useful inference from these experimental
results.
Note: Instead of computing the actual time of an operation on binary search tree, you are advised to
count the number of instructions or number of nodes visited while executing an operation.
2

S-ar putea să vă placă și