Search code examples
c++vectorbubble-sort

BubbleSort Vector


I am trying to sort a vector of objects based on one of the objects attributes. Each Object has an integer value associated with it. I am trying to use a bubblesort to sort the array by descending order but it doesn't seem to be doing anything. Here is what I have tried:

void Database::sort (vector<Play*> &vec) {
  for (int i = 0; i < (vec.size() - 1); i++) {
    if (vec.at(i)->getRelevance() < vec.at((i + 1))->getRelevance()) {
      Play *tempObj = new Play(vec.at(i));
      vec.at(i) = vec.at((i +1));
      vec.at((i + 1)) = tempObj;
    }
  }
}

getRelevance() is the attribute to sort the objects by.


Solution

  • One of the problems with your code is that it only contains one loop! If you want to do bubble sort, you need two nested loops. For example, this would probably work:

    void Database::sort (vector<Play*> &vec) {
        bool have_swapped = true;
        for (unsigned j = 1; have_swapped && j < vec.size(); ++j) {
            have_swapped = false;
            for (unsigned i = 0; i < vec.size() - j; ++i) {
                if (vec[i]->getRelevance() < vec[i + 1]->getRelevance()) {
                    have_swapped = true;
                    Play * tempObj = vec[i];  // Just use:
                    vec[i] = vec[i + 1];      //    std::swap(vec[i], vec[i + 1]);
                    vec[i + 1] = tempObj;     // instead of these three lines.
                }
            }
        }
    }
    

    You see the outer loop? It has two uses. One, it actually ensures that we are combing through the vector while there are still elements out of order (called inversions in algorithm textbooks, I believe,) and two, it lets us not go through and pointlessly check the elements that have "bubbled up" to the end of the vector as a result of previous inner loop iterations.

    But bubble sort is not a good algorithm (unless you are sure your input data are almost sorted, in which case bubble sort can be very efficient.) Instead, you can do something like this:

    std::sort (vec.begin(), vec.end(),
        [](Play * a, Play * b){return b->getRelevance() < a->getRelevance();}
    );
    

    And that's pretty much it.

    Some notes:

    • You have to include <algorithm>.
    • That thing as the third parameter of the function is called a "lambda". Lambdas are basically functions with no names that you can just write in the middle of your code and pass around. I suggest you read up on them, since they are an important concept in computing and programming (independent of language you use.)
    • Since you want the items sorted in descending order of relevance and std::sort sorts ascendingly(?) by default, the lambda returns true when b's relevance is less than a's.
    • Using the standard sort algorithm, in addition to being shorter and sweeter than your hand-rolled code, and a lot more likely to be correct, means that you get very good performance generally (both algorithmic Big-O performance and implementation-wise.) It will certainly be much better that bubble sort (in the general case.)