简体   繁体   中英

bubble sort implementation in c++

the code below is used to implement bubble sort. why is template used in this case? and what is the purpose of swapped variabe. even if i remove swapped variable and swapped condition from loop code still works fine

#include <algorithm>
#include <iostream>
#include <iterator>

template <typename RandomAccessIterator>
void bubble_sort(RandomAccessIterator begin, RandomAccessIterator end) {
  bool swapped = true;
  while (begin != end-- && swapped) {
    swapped = false;
    for (auto i = begin; i != end; ++i) {
      if (*(i + 1) < *i) {
        std::iter_swap(i, i + 1);
        swapped = true;
      }
    }
  }
}

int main() {
  int a[] = {100, 2, 56, 200, -52, 3, 99, 33, 177, -199};
  bubble_sort(std::begin(a), std::end(a));
  copy(std::begin(a), std::end(a), std::ostream_iterator<int>(std::cout, " "));
  std::cout << "\n";
}

ANOTHER IMPLEMENTATION:

template<typename Iterator>
 void bubbleSort(Iterator first, Iterator last)
 {
     Iterator i, j;
     for (i = first; i != last; i++)
         for (j = first; j < i; j++)
             if (*i < *j)
                 std::iter_swap(i, j); // or std::swap(*i, *j);
 }

The template is there simply for convenience of using the function with different types. Implementing the function to use iterators and not a simple array saves you a lot of trouble with pointers and sizes.

The swapped variable indicates to the algorithm that the last run from begin to the end did not result in any swaps. This means that the array is sorted already in this range (and past the end it's sorted as well because that's what was handled in the previous passes) and there is no need to loop until the begin and end iterator are the same. The algorithm will work if you remove this check but could result in a time waste in case of partially sorted arrays.

Let's look at this example:

0: {1   2   5   3   4} (begin = 0, end = 4)
1: {1   2   3   4   5} (begin = 0, end = 3)
2: {1   2   3   4   5} (begin = 0, end = 2)
3: {1   2   3   4   5} (begin = 0, end = 1)
4: {1   2   3   4   5} (begin = 0, end = 0)

You can see that after 0: the array is already sorted, but without the swapped flag the algorithm would not break and continue checking. If the flag is there after 1: the swapped flag is false and the algorithm quits.

Different containers have their own iterator types. For example for one-dimensional arrays there are used pointers as iterators while for objects of the type std::vector there are used iterators defined in this template class.

The variable swapped is used as a criteria whether the elements are already sorted. If there was not swapping of elements of the sequence when it was traversed then it means that the sequence is already sorted.

Take into account that the implementation you showed has undefined behavior due to this statement

while (begin != end-- && swapped) {
                ^^^^

because there is an attempt to decrement the last iterator when the range can be empty. So the implementation is incorrect.

Moreover the algorithm is not efficient. For example a tail of the array can be already sorted after some iteration of the internal loop. However in the external loop the last iterator is moved left only one position.

It is enough to use forward iterators for the bubble sort. In this case you can use the algorithm even with std::forward_list and others containers that do not have random access iterators.

Here is a demonstrative program that shows how the algorithm can be implemented using forward iterators.

#include <iostream>
#include <algorithm>
#include <iterator>
#include <forward_list>

template <typename ForwardIterator>
void bubble_sort( ForwardIterator first, ForwardIterator last )
{
    for ( ForwardIterator sorted = first; first != last; last = sorted )
    {
        sorted = first;
        for ( ForwardIterator current = first, prev = first; ++current != last; ++prev )
        {
            if ( *current < *prev )
            {
                std::iter_swap( current, prev );
                sorted = current;
            }
        }
    }
}

int main() 
{
    int a[] = { 100, 2, 56, 200, -52, 3, 99, 33, 177, -199 };

    bubble_sort( std::begin( a ), std::end( a ) );
    std::copy( std::begin( a ), std::end( a ), 
               std::ostream_iterator<int>( std::cout, " " ) );
    std::cout << "\n";

    std::forward_list<int> lst = { 100, 2, 56, 200, -52, 3, 99, 33, 177, -199 };

    bubble_sort( std::begin( lst ), std::end( lst ) );
    std::copy( std::begin(lst ), std::end( lst ), 
               std::ostream_iterator<int>( std::cout, " " ) );
    std::cout << "\n";
}   

The program output is

-199 -52 2 3 33 56 99 100 177 200 
-199 -52 2 3 33 56 99 100 177 200 

Here in the program there are used an array and an object of the type std::forward_list and the algorithm can be applied to the both containers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM