Recently, we’ve been discussing
sorting and efficiency in lectures. Different sorting algorithms that have
appeared in CSC108 and CSC165 have made a comeback in CSC148. In CSC108, we
were told that there are more than one way to sort a list and that the
different methods of sorting said list have different efficiencies.
Truthfully speaking, the only thing I remember from CSC108,
with regards to this topic, is: “Bubble Sort is a pretty bad sorting algorithm
compared to the alternatives.” The alternatives here are other sorting
algorithms: merge, insert, quick,
With regards to CSC165, big-oh notation makes a comeback. From
what I remember from CSC165, big-oh allows us to model how the runtime of a
function/algorithm grows as the input size increases. Big-oh allowed us to
obtain an upper-bound for the worst-case scenario (i.e. for some sorting
algorithms, like bubble sort, it would be if the elements of the list were in
reverse order). If the worst case has an upper bound, then logically, the other
cases would also be bounded by the same upper-bound.
We use n to denote the number of
items in a list. Thus, as n grows, the runtime of the sorting algorithm should
obviously grow too (unless n is perhaps 0 or 1). The problem is that we need to
determine just exactly HOW the runtime grows. That is, the runtime may not grow
linearly. We can actually trace a sorting algorithm to determine if the
worst-case input for the algorithm grows similarly to another function.
For example, with bubble sort, we compare each element of
the list with its immediate neighbor. We then swap the two elements if
necessary then move on to the next two immediate elements. When the “index”
moves to the end of the list, the index resets to the beginning and does the
entire process again. Only when no swaps are made during an entire pass will
the algorithm be finished. With the first pass, we see that n – 1 comparisons
are made. With the second path, n – 2
comparisons are made. This continues until we reach the (n - 1)th pass, in
which only 1 comparison is made. Thus, the total number of comparisons is:
1+2+3+…+n-2 + n-1 = 0.5n^2 – 0.5n.
The above expression is in big-oh of n^2. However, as
mentioned earlier, there is the possibility of having a BETTER or perhaps even
a BEST case. With bubble sort, this is when all the items are already properly
ordered. Thus, only n-1 comparisons are
made, which is associated with big-oh of n. Although this is true, we need to
keep in mind that very rarely will the best case happen. It’s likely that the
elements of a list aren’t properly ordered. That’s why I think that it’s better
to associate bubble sort with big-oh of n^2. Thus, as n grows, the bubble sort
runtime will grow quadratically.
Using the same idea, we can trace the code for other sorting
algorithms to obtain a better understanding of how the runtime grows as the
input size increases. With more efficient algorithms, log (base 2) n is used as
the algorithm splits the list into two separate parts.
On a different note, I recall
that during one lecture, Professor Heap talked about a sorting algorithm that could
sort a deck of cards like this:
1)
Toss the deck of cards in the air and let the
cards fall.
2)
Pick up the cards and stack them together.
3)
Check to see if they’re properly sorted.
4)
If not sorted, repeat steps 1 -3.
At first, I thought that Professor Heap was joking. This
sorting algorithm is hilariously atrocious (runtime involving factorials!). This
sparked by interest and I found that this sorting algorithm does indeed exist
and is called “robsort”.
From the website says, “it is claimed to be the world’s
least efficient sorting algorithm.” The questions I have now are: “Why would
someone create this?” and “How does this work practically in real life
situations?”