Graded Lab III
Graded Lab III
Instructions:
Page 1 of 3
Swati Mishra
Part 1: Insertion sort algorithm helps to sort an array ( or list of items) by comparing and inserting one
item at a time. Traditional implementation of insertion sort is not very efficient on large lists sizes when
compared with quicksort, or merge sort. You may have already observed this in your graded lab I.
However, some variants of insertion sort are more practical (e.g. Shell Sort). In this part, you will
implement one such variant of insertion sort, using binary search. Such a variant is more commonly
used and particularly helpful when the cost of comparisons is more than the cost of swaps (for example,
sorting through long strings of text). Your goal is to implement a hybrid sorting algorithm that
implements an insertion sort and uses binary search to determine the correct location on which new
elements must be inserted. By using binary search to pre-compute the locations, one can reduce the
number of swaps. To implement this hybrid sort – one that performs insertion sort, by using binary search
to compute the target location of items in a list before swapping them, you must use recursion.
Part 2: Design an experiment to compare performance against traditional insertion sort (number of trials
= 30, number of elements in a list = 500, maximum value of elements in list = 5000), and answer the
following questions in the report:
a. Plot a bar chart showing performance of hybrid sort and traditional insertion sort for all trials.
b. Which of two algorithms performs better?
c. What is the worst-case complexity of hybrid sort?
d. Provide evidence through an experiment design to compare the worst case, best case and average
case performance of your hybrid sort and traditional insertion sort - number of trials = 10, number
of elements in a list = 500, maximum value of elements in list = 5000. Remember to modify your
list generator such as to give you lists for best case, average case and worst case.
Part 3: Binary search of a sorted array takes logarithmic search time. However, if you notice closely, the
insertion of new element takes linear time. By keeping several sorted arrays, you can improve the time for
insertion. For instance, you can SEARCH and INSERT separately on a set of n values. It can go
something like this for a set of n elements:
Let 𝑘 = [lg (𝑛 + 1), and let the binary representation of n be {𝑛!"# , 𝑛!"$ , … , 𝑛% }. Maintain k sorted
arrays 𝐴% , 𝐴# , … , 𝐴!"# where for 𝑖 = 0,1, … . , 𝑘 − 1, the length of the array 𝐴& is 2& . Each array is either
full or empty, depending on whether 𝑛& = 1 𝑜𝑟 𝑛& = 0 , respectively. The total number of elements held
in all k array is therefore ∑!"# &
&'% 𝑛& 2 = 𝑛. Although each individual array is sorted, elements in different
arrays bear no relationship to each other. This can allow binary search to be implemented using dynamic
programming, we will cover dynamic programming in coming classes.
Implement the SEARCH, INSERT and DELETE operations for binary search using the above
description. For this, the code has not been provided. Feel free to go back to previous labs and use the
Binary Search implementations discussed there, to build upon.
Part 4: In this section, compare your implementation of Part 2 against traditional implementations of
binary search (1, 2 and 3) which have been provided in the accompanying python file. Design a suitable
experiment to compare the performance against this dynamic implementation (number of trials = 30,
number of elements in a list = 500, maximum value of elements in list = 10,000). Answer the following
questions in the report:
a. When does dynamic binary search outperform others?
b. When is it an overkill?
c. Describe the overall performance you observe in your chart.
Page 2 of 3
Swati Mishra
Part 5: In the code posted with this document, you will find a 𝑢𝑛𝑘𝑛𝑜𝑤𝑛() function. It takes a graph as
input. Do some reverse engineering. Try to figure out what exactly this function is accomplishing. You
should explore the possibility of testing it on graphs with negative edge weights (create some small
graphs manually for this). Determine the complexity of this function by running some experiments as
well as inspecting the code. Through your experiments, answer the below questions:
a. What does the code do? Can you name the algorithm?
b. What is the complexity of the algorithm?
c. Given what this code does, is the complexity surprising? Why or why not?
Part 6: While Prim’s algorithm is a greedy algorithm, that starts with one node and builds a minimum
spanning tree (MST) one edge at a time, Krushkal’s begins with all vertices and no edges, and adds one
weighted edge to MST set in increasing order of weight (while trying to avoid any cycles). In this part,
implement Krushkal’s algorithm using the heap class discussed in class. You may add more helper
functions to the heap class if you need to. Compare the performance of Prim’s (using heap) and
Krushkal’s (using heap) on 50 randomly generated graphs (number of nodes = 7, choice of edges is
yours). You are free to use any random graph generator function you implemented in graded lab II.
Please note that use of heapq or any other library functions is not permitted. Summarize your
observations of comparing the two algorithms in maximum 3-4 lines in the report and include the charts.
Feel free to review Krushkal’s algorithm from material for the book you are using or this source.
Page 3 of 3