4

伙计们,我有以下代码,它位于一个遍历树的大 while 循环中。这是我能得到这个例程的最快速度,但我必须使用 goto。我从根本上并不反对 goto,但如果我能避免它们,我愿意。(拜托,我不是要发动一场火焰战争。)

约束:

  1. current=current->child()很昂贵(它是 a ) ,shared_ptr所以我想不惜一切代价尽量减少对该操作的使用。
  2. 操作后current应该是它找到的最后一个孩子。
  3. cnt必须计算它遇到的每个孩子。
  4. cnt++ 将被其他一些操作(或几个操作)替换,并且应该只出现一次:)

编码:

insideloopy:
cnt++;
if ( current->hasChild() )
{
    current = current->child();
    goto insideloopy;
}

编辑:对不起,最初忘记提及 cnt++ 应该只出现一次。这将是节点上的某种操作,因此应该只存在一次。我也试图避免进行另一个函数调用。

4

8 回答 8

26

原始答案

假设这是 C 或 C++:

while (cnt++, current->hasChild())
{
    current = current->child();
}

我通常不是逗号运算符的忠实粉丝,但我也不喜欢重复自己:)

更新了“有趣”的答案

在了解到这cnt++实际上是一些多行操作之后,这种特殊的语法会不太理想。更符合您接受的答案的内容会更好。

如果你想变得非常时髦,这也可以:

do 
{
    cnt++;
} while (current->hasChild() && (current = current->child()));

现在我觉得很脏,因为我滥用了&&操作员的短路:)

理智的回答

除了紧凑性练习和争取可读代码之外,我不得不得出结论,现有答案之一是最适合的(为了完整起见,我只是将其包括在内):

while (true)
{
   cnt++;
   if (!current->hasChild()) break;
   current = current->child();
}

编译器while (true)会将其优化为常规的无限循环,因此只有一个条件语句(如果您关心的话)。

唯一与此解决方案相反的是,如果您的节点操作是一段很长的代码。我不太介意无限循环,只要我一眼就能看出它们在哪里终止。再说一次,如果它真的很长,无论如何它应该是一个函数。

于 2009-08-19T18:24:22.397 回答
18
cnt++;
while(current->hasChild())
{
   cnt++;
   current = current->child();
}

编辑:

如果您只希望 cnt++ 在您的代码中出现一次:

while(true)
{
    cnt++;
    if(current->hasChild())
       current = current->child();
    else
       break;
}
于 2009-08-19T18:22:31.980 回答
11
insideloopy:
cnt++;
if ( current->hasChild() )
{
    current = current->child();
    goto insideloopy;
}

我喜欢无限循环。

while (true) {
   cnt++;
   if (!current->hasChild()) break;
   current = current->child();
}

当然,您可以通过许多其他方式做到这一点(请参阅其他答案)。做一会儿,把检查放在一会儿等。在我的解决方案中,我想几乎映射到你正在做的事情(一个无限的goto,除非中断)

于 2009-08-19T18:28:37.803 回答
3

您可以使用break在代码中间跳出循环:

while (true) {
   cnt++;
   if (!current->hasChild()) break;
   current = current->child();
}
于 2009-08-19T18:30:15.803 回答
0
while (current->hasChild())
{
    cnt++;
    current = current->child();
}

还是我错过了什么?

于 2009-08-19T18:25:20.837 回答
0

current->child()如果它还没有孩子,我会调查返回 NULL 的可能性——这似乎是最好的结果,在这种情况下让它未定义似乎容易出错——然后使用:

for (; current; current = current->child())
{
    cnt++;
}
于 2009-08-19T19:02:18.000 回答
0
for(cnt++ ; current->hasChild() ; cnt++) {
   current = current->child();
}
于 2009-08-19T18:43:00.333 回答
0

没有中断语句:

notDone=true;
while(notDone){
   cnt++;
   if ( current->hasChild() ){
       current = current->child();
   } else {
       notDone=false;
   }
}
于 2009-08-19T20:23:07.230 回答