【问题标题】:for each loop in C++对于 C++ 中的每个循环
【发布时间】:2019-01-24 01:42:52
【问题描述】:

在练习排序算法时,发现一个关于for each 的奇怪问题。我不确定哪里出错了,所以把整个代码贴在下面:

#include <algorithm>
#include <functional>

template <class T, class U = std::greater<>> // std::greater<> require C++14
void bubbleSort(T begin, T end, U comp = U())
{
    for(auto i = end; i != begin; i--) {
        for(auto j = begin; j != i; j++) {
            if(comp(*j, *i)) {
                std::swap(*j, *i);
            }
        }
    }
}

template <class T, class U = std::greater<>> // std::greater<> require C++14
void bubbleSort2(T begin, T end, U comp = U())
{
    auto low = begin;
    auto high = end;
    while(low < high) {
        for(auto i = low; i != high; i++) {
            if(comp(*i, *(i + 1))) {
                std::swap(*i, *(i + 1));
            }
        }
        high--;
        for(auto i = high; i != low; i--) {
            if(comp(*(i - 1), *i)) {
                std::swap(*i, *(i - 1));
            }
        }
        low++;
    }
}

问题来了:

int main()
{
    std::array<int, 10> s = {5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
    bubbleSort(s.begin(), s.end());

    for(auto i = 0; i < s.size(); i++) // Loop1
        std::cout << s.at(i) << " ";

    std::cout << std::endl;

    for (auto a : s) { // Loop2
        std::cout << a << " ";
    }
    return 0;
}

一开始我只写了Loop2来测试输出,但我观察到输出是:0 1 2 2 3 4 5 6 7 8。然后我添加Loop1,输出变为正确: 0 1 2 3 4 5 6 7 8 90 1 2 3 4 5 6 7 8 9。我认为排序功能应该有问题,但是为什么添加Loop1可以解决它? (两者都有相同的行为)

编译器是mingw32。

感谢@FeiXiang的评论,把固定代码放在GitHub

还有@Aconcagua 的推荐,改成:

template <class T, class U = std::greater<>> // std::greater<> require C++14
void bubbleSort3(T begin, T end, U comp = U())
{
    while(end != begin) {
        for(auto i = std::next(begin); i != end; ++i)
            if(comp(*(i - 1), *i))
                std::swap(*(i - 1), *i);
        end--;
    }
}

【问题讨论】:

  • 您在冒泡排序函数中取消引用结束迭代器,调用未定义的行为。
  • 只是理论上的问题(两者都是 O(n^2)),我认为它是选择排序而不是冒泡排序(第一个变体),冒泡排序会交换 neighbouring元素,你交换任意距离的元素......
  • 在您的第二个变体中,您只是“获得”了代码复杂性,但您不会通过第二个循环减少比较次数。我建议放弃它,只拥有while(end != begin) { for(auto i = std::next(begin), i != end; ++i) comp(*(i-1), *i);} --begin; }
  • @Aconcagua 谢谢,我将尝试比较实际的时间复杂度。

标签: c++ sorting for-loop c++14


【解决方案1】:

“i”应该从“end-1”开始

for(auto i = end-1; i != begin; i--)

因为“end”指向数组中最后一个元素的下一个位置。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-06
    • 2014-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-22
    相关资源
    最近更新 更多