switch-case 结构是否以二分搜索的形式实现?

2024-05-02

我想知道如何switch-case语句执行:

Example

假设有以下代码:

Scanner sc = new Scanner(System.in);
int v = sc.nextInt();
switch(v) {
    case 0 :
        System.out.println("Zero");
        break;
    case 1 :
        System.out.println("One");
        break;
    case 2 :
        System.out.println("Two");
        break;
    //...
    default :
        System.out.println("No one digit number");
}

可以将其实现为:

if(v == 0) {
    System.out.println("Zero");
}
else if(v == 1) {
    System.out.println("One");
}
else if(v == 2) {
    System.out.println("Two");
}
//...
else {
    System.out.println("No one digit number");
}

但更有效的方案是:

if(v >= 0 && v <= 9) {
    if(v <= 5) {
        if(v <= 2) {
            if(v <= 1) {
                if(v == 0) {
                    System.out.println("Zero");
                }
                else {
                    System.out.println("One");
                }
            else {
                System.out.println("Two");
            }
        }
        //...
    }
    //...
}
else {
    System.out.println("No one digit number");
}

这一点很重要,因为有些程序(如编译器编译器)会编写 Java/C#/C++ 源代码,从而生成非常大的 switch 语句。


Switch/case 语句根据 case 范围,使用二元决策树和跳转表的组合来实现。

  1. 对于简单的 switch 语句(2 - 3 种情况),发出简单的 if 语句通常更有效,具体取决于值的密集程度(例如 1 2 3 与 1 2 9)。

  2. 对于具有单个密集组的较大基数切换,通常使用直接或间接基于测试值的跳转表。

  3. 对于稀疏组或密集组和稀疏组的混合,二元决策树用于平分组列表,并在组内使用跳转表(树的叶子)。

所以答案是,是的,有时,但不是那么简单。

可以用默认跳转填充“空”案例槽,以允许构建密集范围。对于小型分支或针对非整数值的分支,开关将被重写,就像条件语句一样(例如允许在字符串或正则表达式上进行切换的语言)。在您的示例中,数字 0-9 的情况肯定会被编码为查找表,因为它是一个密集组。

在所有情况下,二元决策树都是发出高效 switch / case 结构的重要组成部分。

.NET CLR 甚至有一个接受跳转表的操作码,它隐藏了默认情况的处理,这允许运行时验证代码是否安全,而无需进行完整的流程分析。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

switch-case 结构是否以二分搜索的形式实现? 的相关文章

  • 在 PHP 5.5.9 中的 PHP 开关中使用常量

    安装 PHP 5 5 9 后Ubuntu 14 04 https en wikipedia org wiki Ubuntu version history Ubuntu 14 04 LTS 28Trusty Tahr 29 Trusty T
  • Haskell 中的 Futamura 投影的证明

    我读了 Dan Piponi 的优秀博客文章二村博士的三个投影 http blog sigfpe com 2009 05 three projections of doctor futamura html 在文章的最后 他有一个附录 其中包
  • 使用矢量化为 iPhone 编译 Eigen 库

    我正在努力为 iPhone 4 编译 Eigen 库 该库具有带有 armv7 指令集的 ARM 处理器 到目前为止 当我指定预处理器定义 EIGEN DONT VECTORIZE 时 一切正常 但由于一些性能问题 我想使用armv7优化的
  • 从 Java / C# 角度理解 C++ 编译器

    我是一名经验丰富的 Java C 程序员 最近开始学习 C 问题是 我无法理解如何构建各种头文件和代码文件 这似乎主要是由于我对编译器如何将所有内容链接在一起缺乏了解 我尝试阅读一些教科书 但我的先入之见受到我的 Java 和 C 知识的影
  • 错误:“;”之前应有构造函数、析构函数或类型转换令牌?

    我正在尝试编译代码来测试读取和打印数据文件的函数 但出现我不明白的编译错误 错误 预期的构造函数 析构函数或 之前的类型转换 令牌 相关代码文本墙如下 struct Day int DayNum int TempMax int TempMi
  • 语法分析和语义分析有什么区别?

    据我了解 Parser由词法分析 句法分析和语义分析三个阶段组成 Lexical 它将我的输入分割成标记 例子 123 100 0 gt 123 100 0 语法 它将研究标记并检查它们是否彼此有意义 我遇到的问题是理解最后阶段的 语义解析
  • 适用于 Windows 的 C++11 编译器

    我刚刚在 Channel9 上看了一些视频 我发现 lambda 之类的东西真的很酷 当我尝试复制该示例时 它失败了 auto也没用 我正在使用诺基亚的 qtcreator 它随 gcc 4 4 0 一起提供 我想知道哪个编译器实现了有趣的
  • switch case 与 if else [重复]

    这个问题在这里已经有答案了 我想知道以下代码编译成汇编的方式是否有任何区别 我听说 switch case 比 if else 更有效 但在这个例子中我不太确定情况是否如此 if x 1 else if x 2 else and switc
  • Go1编译器如何工作?

    我在一个学校项目中接触 Go 大约一个月了 我注意到 src pkg go 文件夹中的 go ast go token go parser 等包 但是 gc 编译器基于位于 src cmd gc 中的 C 文件 我的问题是关于 Go1 中用
  • 如何让 gcc/clang 警告 switch 语句中缺少中断

    有什么办法可以使gcc or clang警告 switch 语句中缺少中断 具体来说 我几乎总是希望 case 语句以中断结束 如果我不这样做的话 如果我能让编译器抱怨 那就太好了 如果它会寻找一个break语句或一个 fall throu
  • switch 在 Visual C++ 中如何编译?它的优化程度和速度如何?

    我发现我只能在 C 中使用数值switch陈述 我认为它和一堆更深层的区别if else s 因此我问自己 如何switch与 不同if elseif elseif在运行速度 编译时优化和一般编译方面 我这里主要说的是MSVC 开关通常被编
  • C# 编译器错误?为什么这个隐式用户定义转换无法编译?

    给定以下结构 public struct Foo
  • 带有 case OR 运算的 VB.NET select case 语句逻辑是什么?

    我正在使用一个Or https msdn microsoft com en us library 06s37a7f aspx我的案例表达式中的声明 尽管我有一个在此范围内的值 但它没有找到匹配项 为什么不 示例代码 Select Case
  • 用于编译/反编译二进制数据文件的通用实用程序或库?

    我有各种二进制文件格式 我需要将其转储为某种文本格式 编辑然后重新编译 可能是二进制格式的稍微不同的版本 当然 我可以用 C C 编写一堆实用程序代码来完成这种事情 并且可能利用一个库来处理文本方面的事情 XML 或 JSON 或其他 但这
  • 使用 gcc 的中间 GIMPLE 格式

    根据本文 http en wikipedia org wiki Intermediate languagegcc 在生成代码之前使用多种中间格式 我读到 GIMPLE 格式使用三个地址代码 这似乎是最容易使用的中间语言 但我需要更多细节 因
  • Powershell“特殊”开关参数

    我有下面的powershell功能 Function Test Param Parameter string Text default text Write Host Text Text 我希望能够像下面这样调用这个函数 测试 文本 应该在
  • 是否有像 gccxml 这样的用于生成包装器的 C 标头解析器工具?

    我需要为一种新的编程语言编写一些 C 标头包装器 并且想要类似 gccxml 的东西 但不完全依赖 gcc 以及它在 Windows 系统上带来的问题 只需要读C而不是C 只要有完整的文档记录 任何格式的输出都可以 Linux Solari
  • 特殊名称属性还允许哪些其他巧妙的技巧?

    研究中一个问题 https stackoverflow com questions 13259162 vb net power operator overloading from c sharp关于实现 Visual Basic Power
  • 是否可以在Linux上将C转换为asm而不链接libc?

    测试平台为Linux 32位 但也欢迎 Windows 32 位上的某些解决方案 这是一个c代码片段 int a 0 printf d n a 如果我使用 gcc 生成汇编代码 gcc S test c 然后我会得到 movl 0 28 e
  • 在Java中使用命令行编译多个包

    您好 我一直在使用 IDE 但现在我需要从命令行运行和编译 问题是我有多个软件包 我试图找到答案 但没有任何效果 所以我有 src Support java files Me java files Wrapers java files 你知

随机推荐

  • 这是可插拔组件本地化的好解决方案吗?

    我问了一个question https stackoverflow com questions 1504363 how should i localise pluggable components以前只有一个答案 我现在已经花了一些时间来研
  • 比较元胞数组中的字符串

    我试图在单词列表中找到最常见的单词 到目前为止 这是我的代码 uniWords unique lower words for i 1 length words for j 1 length uniWords if uniWords j lo
  • 如何对 Django 视图进行单元测试?

    我想开始将单元测试集成到我的 Django 项目中 并且我发现对视图进行单元测试很棘手 因为 Django 使用函数实现视图的方式 例如 如果函数有 URL 则每个函数都是 Django 中的视图 页面 如何对 Django 视图进行单元测
  • 如何使用 hibernate JPA 2 以二进制形式存储 uuid

    我有一个关于通过休眠持久化 JPA2 在数据库中以二进制形式存储字符串uuid的问题 我现在正在使用这段代码 private UUID id Id Type type uuid char GeneratedValue generator s
  • 不小心删除了Android布局文件

    我不小心从我的 Android 项目中删除了一个布局文件 有什么办法可以拿回来吗 自从做完之后我就再也没碰过 而且我在其他地方没有该文件的副本 如果您的 bin 文件夹中有该 apk 那么您很幸运 使用apktool https code
  • 使用 ffmpeg 将视频与其自身连接,但相反

    我能够逆转 ffmpeg i input mp4 vf reverse output reversed mp4 我可以连接 ffmpeg i input mp4 i input mp4 filter complex 0 0 0 1 1 0
  • 如何以编程方式迭代所有 CMake 目标?

    有没有办法从顶层获取 CMake 项目的所有目标CMakeLists txt 即以编程方式迭代目标 我想要这样做的原因是将一些 XCode 特定设置应用于每个目标 if CMAKE GENERATOR MATCHES Xcode inclu
  • 受保护属性的通用 getter 和 setter

    考虑这个 TypeScript 类 它通过将实现分为超类和子类来提供类型检查的通用 getter 和 setter class ICompetence protected id number undefined protected name
  • 抓取网页时调用 javascript 函数

    我正在使用 python 抓取网页 该页面有
  • emacs 启动后更改 X11 窗口标题

    当我启动 emacs 时 我可以使用 title 选项来控制保存 emacs 应用程序的 x 窗口的标题 emacs从elisp启动后可以更改标题吗 M x set frame name NewName RET 和来自 elisp set
  • videoMinFrameDuration 已弃用

    当我将 Xcode 从 4 6 更新到 5 1 时 ios7 中不推荐使用 videoMinnFrameDuration void setFrameRate NSInteger frameRate frameRate frameRate i
  • Angular2 RC6 HttpModule手动注入

    我正在将一个项目从 angular2 RC4 迁移到 RC6 并且我有一个自定义表单验证器 需要Http 在迁移之前我使用了ReflectiveInjector与HTTP PROVIDERS 但是对于 RC6 这不再可能了 因为HTTP P
  • 通过电子邮件搜索将 Excel 2003 中的数据行复制并粘贴到不同的工作表

    在任何人发表任何言论之前 我已经浏览了几篇与此类似想法相关的帖子 采用不同的搜索条件 然后对其进行修改 但我无法让宏正常工作 这可能是由于我缺乏编程知识 我想做的就是 search的电子邮件地址工作表1如果找到 则将整行复制到下一个空闲行工
  • 如何将数据框随机分成三个具有给定行数的较小数据框

    使用 R 我想将一个数据帧随机拆分为三个较小的数据帧 第一个占总观测值的 80 第二个和第三个分别占总观测值的 15 和 5 三个数据框不能有任何重叠 你有什么建议吗 这是一个快速函数 可以根据您在 props 参数中指定的值的数量分成任意
  • iPhone应用程序NSNumber内存泄漏

    我遇到了内存泄漏 但我不知道它从哪里来以及如何修复它 在某些时候 我计算两个位置之间的距离 double calc self getDistance location to otherLocation NSNumber distance N
  • 如何使用Python的RotatingFileHandler

    我正在尝试进行测试运行logging模块的RotatingFileHandler https docs python org 3 library logging handlers html logging handlers Rotating
  • 检查 C# 中泛型方法的类型参数

    是否可以在 C 中执行类似的操作 public void DoSomething
  • 正式协议对象有什么用

    我们可以在源代码中创建协议对象 但是正式的协议对象有什么用呢 Protocol myObj protocol protocolName 您可以使用它来检查对象是否符合协议 anotherObject conformsToProtocol m
  • 使用 MySQL 检测垃圾邮件发送者

    我发现越来越多的用户在我的网站上注册 只是为了向其他用户发送重复的垃圾邮件消息 我添加了一些服务器端代码来使用以下 mysql 查询检测重复消息 SELECT count content as msgs sent FROM messages
  • switch-case 结构是否以二分搜索的形式实现?

    我想知道如何switch case语句执行 Example 假设有以下代码 Scanner sc new Scanner System in int v sc nextInt switch v case 0 System out print