Why this for loop doesn't do the same that the while loop?

100 Views Asked by At

I'm trying to implement the cocktail sort, and in the main loop I'm trying to use a for loop instead of a while, but it doesn't give me the same results. Here is the code of the while loop:

template<typename T>
void cocktail(std::vector<T>& vec)
{
    std::size_t beg = 1;
    std::size_t end = vec.size()-1;
    bool change = true;

    while((beg < end) && (change))
    //for(std::size_t beg = 1, end = vec.size() - 1; (beg < end) && (change); change = false)
    {
        change = false;
        for(std::size_t j = beg; j <= end; j++){
            if(vec[j] < vec[j-1]){
                std::swap(vec[j-1], vec[j]);
                change = true;
            }
        }
        end--;
        for(std::size_t j = end; j >= beg; j--){
            if(vec[j] < vec[j-1]){
                std::swap(vec[j-1], vec[j]);
                change = true;
            }
        }
        beg++;
    }
}

Output:

Before: 3 2 0 9 5 7 8 1 4 6
 After: 0 1 2 3 4 5 6 7 8 9

And here is the for loop:

template<typename T>
void cocktail(std::vector<T>& vec)
{
    //std::size_t beg = 1;
    //std::size_t end = vec.size()-1;
    bool change = true;

    //while((beg < end) && (change))
    for(std::size_t beg = 1, end = vec.size() - 1; (beg < end) && (change); change = false)
    {
        //change = false;
        for(std::size_t j = beg; j <= end; j++){
            if(vec[j] < vec[j-1]){
                std::swap(vec[j-1], vec[j]);
                change = true;
            }
        }
        end--;
        for(std::size_t j = end; j >= beg; j--){
            if(vec[j] < vec[j-1]){
                std::swap(vec[j-1], vec[j]);
                change = true;
            }
        }
        beg++;
    }
}

Output:

Before: 3 2 0 9 5 7 8 1 4 6
 After: 0 2 1 3 5 7 8 4 6 9

Do you know why I'm getting different output? My code is located here if you want to see the main file or something.

3

There are 3 best solutions below

0
On BEST ANSWER

In your For Loop remove (change = false) from inside the for() statement. Let that for statement be

for(std::size_t beg = 1, end = vec.size() - 1; (beg < end) && (change);)
{
    // Write here
    change= false;
    ......
}

It would work.

Explanation: In your while loop code, your change is set to false at the first step. But in your for loop the change = false statement is set to false at the end of the loop. As the third argument of for loop executed as the last statement of the loop.

Consider an example:

for(i=0;i< n;i++)

i is incremented at last not at first. This is the problem with your solution.

0
On

In a for loop, the "increment" (3rd part) is executed before the condition (2nd part) is evaluated. In your case

for(std::size_t beg = 1, end = vec.size() - 1; (beg < end) && (change); change = false)

you are not incrementing a variable, but rather setting change = false;. However, this is still executed before the condition is evaluated. Therefore, the condition is always false. In your while loop, instead, you are setting change = false; inside the loop, after the condition has been evaluated. This means your 2 loops are not equivalent.

0
On
for (size_t i = 0; i < 10; i++)
    body();

is equivalent to

size_t i = 0;
while (i < 10) {
    body();
}

Your code uses

for (bool change = true; change; change = false)
    body();

which is equivalent to

bool change = true;
while (change) {
    body();
    change = false;
}

After the first pass through this loop, change will always be false during the conditional test at the start of the loop.

for ( initial ; condition ; iterate )
               ^-------------------v