Daily Program for 4/22/2013
If you’ve ever been exposed to sorting algorithms, then the logical first step is implementing the bubble sort algorithm. Sadly, the bubble sort algorithm has efficiency issues stemming from the fact that it unidirectionally sorts the list on each pass. Today, we will implement the cocktail sort in C++ using templates to provide a more general and bidirectional version of the bubble sort algorithm.
Problem Statement for the Cocktail Sort Algorithm:
Implement a bidirectional bubble sort algorithm which takes as input a vector of values which can be represented numerically. Return the sorted vector to the user.
Code:
#include <iostream> #include <vector> #include <algorithm> #include <iterator> template <class T> void cocktailSort(std::vector<T>& v) { int sorted; while (sorted != 0) { sorted = 0; for (typename std::vector<T>::iterator it = v.begin(); it != v.end(); ++it) { if (it + 1 != v.end()) { if (*it > *(it + 1)) { std::iter_swap(it, it + 1); sorted += 1; } } } for (typename std::vector<T>::reverse_iterator rit = v.rbegin(); rit != v.rend(); ++rit) { if (rit + 1 != v.rend()) { if (*rit < *(rit + 1)) { std::iter_swap(rit, rit + 1); sorted += 1; } } } } } int main(int argc, const char *argv[]) { int i,j,k; std::vector<int> myInts; std::cout << "How many elements do you want to add to the vector?\n --> "; std::cin >> j; for (i = 0; i < j; ++i) { std::cout << "Element " << i + 1 << ": "; std::cin >> k; } std::cout << "The ordered list is as follows:" << std::endl; cocktailSort(myInts); for (std::vector<int>::iterator it = myInts.begin(); it != myInts.end(); it++) { std::cout << "Element " << it - myInts.begin() << ": " << *it << std::endl; } return 0; }
Sample Session:
How many elements do you want to add to the vector? --> 5 Element 1: 2 Element 2: 5 Element 3: 1 Element 4: -23 Element 5: -192 The ordered list is as follows: Element 0: -192 Element 1: -23 Element 2: 1 Element 3: 2 Element 4: 5
Explanation:
In order to implement a generalized version of the cocktail sort algorithm, we begin by defining a template of class T. As a side note, I’ve seen a lot of code floating around with template <typename T> statements in it and I’d like to note that this is roughly equivalent to using the <class T> statement. The outer loop is the same as in bubble sort and the first inner loop is also the same with the exception of the inclusion of a typename declaration in front of the iterator initialization. This serves to give the compiler information about the amount of memory that must be iterated between each element in the vector. Our second for loop is where the magic happens. We use a reverse_iterator, which essentially means that it starts at the end of the vector and goes to the beginning – 1 of the vector. The nice thing about using a reverse_iterator is that we can use the rbegin() and rend() methods to maintain a pretty normal loop invariant. We also flip our conditional expression since we are now checking whether or not the element is less than the element + 1. As another side note, it’s good to always use std::<something> notation in generalized functions since we won’t know if the user of our function will necessarily have been using the std namespace.
Thanks for reading and stay tuned for more algorithm implementations in the future!
