22

假设我有一个如下的 switch 语句

switch(alphabet) {

    case "f":
        //do something
        break;

    case "c":
        //do something
        break;

    case "a":
        //do something
        break;

    case "e":
        //do something
        break;

}

现在假设我知道拥有Alphabete 的频率最高,然后分别是 a、c 和 f。所以,我只是重组了case语句顺序,并将它们制成如下:

switch(alphabet) {

    case "e":
        //do something
        break;

    case "a":
        //do something
        break;

    case "c":
        //do something
        break;

    case "f":
        //do something
        break;
}

第二个switch语句会比第一个switch语句快吗?如果是,并且如果在我的程序中我需要switch多次调用此语句,那会是一个实质性的改进吗?或者如果没有,我如何使用我的频率知识来提高性能?

4

4 回答 4

23

没有那么多,你应该担心。这当然不是可以预测的事情。

使用字符串大小写标签,编译器实际上使用了一个内部哈希表,将字符串映射到跳转表中的索引。所以这个操作实际上是 O(1) - 与标签的数量无关。

对于整数标签,我相信生成的实际代码取决于标签的数量以及数字是否连续(或“几乎”连续)。如果它们是连续的 (1, 2, 3, 4, ...),那么它们将被转换为一个跳转表。如果它们很多,则将使用 Hashtable+jump 表(如字符串)。如果只有几个标签,而且它们不是表格,要立即转化为跳转表,只有这样才会转化为一系列 if..then..else 语句。

但是,一般而言,您应该编写代码以便您可以阅读它,而不是让编译器可以生成“更快”的代码。

(Note my description above is an implementation detail of how the C# compiler works internally: you shouldn't rely on it always working like that -- in fact, it might not even work exactly like that now, but at least it's the general idea).

于 2010-05-12T03:46:18.283 回答
3

It depends on how the compiler implements the switch statement.

First, you can't arbitrarily permute the order; if you have one case block in a C-like language (C, C++, C#, Java, ...), and that case block does not terminate in break, you can't rearrange the cases because the absence of the break means the compiler must implement fall-through to the next case. If we ignore this special situation, you can permute the rest of the cases.

如果案例的数量很少,编译器可以通过一系列比较来实现案例测试。如果事例数量适中,则可以从这些事例中构建平衡二叉树。如果 case 的数量很大,大多数编译器都会在 switch 值上实现索引分支(如果它来自密集集)。如果案例值集合的一部分是密集的,而部分不是密集的,则编译器可以使用二叉树将案例分成组以选择哪个密集集,以及密集集中的索引跳转。(事实上​​,编译器在技术上可能会做任何将控制权传递给适当情况的事情,但大多数情况下是上述情况之一)。

您可以看到顺序可能很重要,也可能不重要,具体取决于编译器如何实现开关。对于大多数优秀的编译器来说,这并不重要。

于 2010-05-12T03:54:07.203 回答
2

对于相对较小的一组值,它们具有相同的性能。我之前试过检查 C 程序的汇编代码,编译器会根据你在 switch 语句中的所有值创建一个跳转表。

但是,如果 case 值太多,则可以肯定它们会退化为if else if,因此将 case 'E' 放在首位肯定会加快速度。

它也适用于 C#,C# 还为带有小集合的 switch 语句生成跳转表,尽管仅针对相邻值。所以它是 O(1),即使第一个值不匹配,也没有多重测试。

于 2010-05-12T03:45:30.377 回答
-3

我认为 switch case 的方式是它会从上到下遍历所有案例以找到一些匹配项。如果匹配,它将停在那里。

因此,如果您更改了频率情况的优先级,答案是肯定的,它可以以某种方式帮助提高性能。但我相信这不会有太大帮助。

于 2010-05-12T03:42:04.423 回答