2

我需要遍历 n 对整数: (0, 1), (1, 2), (2, 3) ... (n-2, n-1), (n-1, 0)

最好的方法是什么?

  1. 使用模运算:

    for (int i = 0; i < n; i++){
        int a = i;
        int b = (i + 1)%n
        //MaaaanyLinesOfDoSomethingWithAAndB
    }
    
  2. 使用三元运算:

    for (int i = 0; i < n; i++){
        int a = i;
        int b = (i + 1 == n ? 0 : i + 1)
        //MaaaanyLinesOfDoSomethingWithAAndB
    }
    
  3. 或者:

    for (int i = 0; i < n; i++){
        int a = i;
        int b = (i + 1 >= n ? 0 : i + 1)
        //MaaaanyLinesOfDoSomethingWithAAndB
    }
    
  4. 另一个想法?假设有 maaaany 行做某事,如果我们执行 (0, 1), (1, 2), (2, 3) ... (n-2, n-1) 部分和(n-1, 0) 部分分开。

哪种操作最有效?

编辑#1 对不起,我想我没有正确地问我的问题。我想知道哪个操作员动作更快(例如秒或时钟滴答声)。我还决定做一些小实验,只用 clock() 函数来测量它。这是我的代码:

#include <time.h>
#include <limits.h>
#include <string>
#include <iostream>
using namespace std;

typedef void (*fun) (int a);

void DoSomething(int i){
    int a = i;
}

void ModuloOperation (int n){
    for (int i = 0; i < n; i++)
        DoSomething((i + 1) % n);
}

void TernaryEqual (int n){
    for (int i = 0; i < n; i++)
        DoSomething(i + 1 == n ? 0 : i + 1);
}

void TernaryBiggerEqual (int n){
    for (int i = 0; i < n; i++)
        DoSomething(i + 1 >= n ? 0 : i + 1);
}

void SplitIntoTwoParts (int n){
    for (int i = 0; i < n - 1; i++)
        DoSomething(i + 1);
    DoSomething(n - 1);
}

int main(){

    const int n = INT_MAX;

    string testNames[] = {
        "Modulo", 
        "Trenary equal", 
        "Trenary bigger equal", 
        "Split into two parts"
    };

    fun tests[] = {
        ModuloOperation, 
        TernaryEqual, 
        TernaryBiggerEqual, 
        SplitIntoTwoParts
    };

    clock_t t;

    for (int i = 0; i < sizeof(testNames)/sizeof(testNames[0]); i++){

        t = clock();
        tests[i](n);
        t = clock() - t;

        cout<<testNames[i]<<": "<<((float)t)/CLOCKS_PER_SEC<<" seconds\n\n";
    }

    return 0;
}

这是一个输出

模数:53.867 秒

三元相等:36.684 秒

三元大等于:37.299 秒

分成两部分:31.37 秒

所以看来pswg的思路不仅是最干净的,也是最好的。

再一次,对不起我的错误,我不是母语人士,我还在学习。

4

1 回答 1

8

你提到如果你单独做'maaaany'行会看起来很难看。上述选项都不是特别漂亮。所以也许最好将这个丑陋的逻辑封装在一个方法中,并在你的循环中使用一些更优雅的代码。

为了可读性,我可能会这样做:

for (int i = 0; i < n - 1; i++){
    DoStuff(i, i + 1);
}
DoStuff(n - 1, 0);

// elsewhere
void DoStuff(int a, int b)
{
    //MaaaanyLinesOfDoSomethingWithAAndB
}

如果“maaaany”行需要使用多个局部变量,并且您不想将它们全部传递给DoStuff方法,则可能需要考虑使用闭包,尽管它几乎不会提高代码的可读性尽可能适当的功能分解。像这样的东西:

Action<int, int> doStuff = (a, b) =>
{
    //MaaaanyLinesOfDoSomethingWithAAndB
};

for (int i = 0; i < n - 1; i++){
    doStuff(i, i + 1);
}
doStuff(n - 1, 0);

或者您可能需要将“maaaany”行重构为一个单独的工人类,但如果不了解这些行中的更多内容,就很难说。

于 2013-05-30T20:15:10.563 回答