【你问我答】如何优化代码中的大量if/else?

问题描述:

如何优化代码中的大量if/else?

回答有奖:

选取一位认真回答问题的牛友,赠送200牛币!
▶回答尽量有自己的思考,不要单纯的只是复制粘贴定理定义,或者他人blog哦~

你问我答问题汇总:点击进入
关注你问我答栏目:点击关注

你问我答 - 答问题,成大佬,拿牛币!
你问我答是牛客新栏目,每周1期几个问题,
牛友在问题贴下留下自己的知识,经验与见解,
帮助更多牛友了解更多技术相关知识!
#悬赏#
全部评论
说几个和大家不一样的(不用switch case) 你需要先弄清楚if-else的工作原理。if就像一个铁路分叉道口,在CPU底层这种通讯及其不好的地方,在火车开近之前,鬼知道火车要往哪边开,那怎么办?猜!如果猜对了,它直接通过,继续前行。如果猜错了,车头将停止,倒回去,你将铁轨扳至反方向,火车重新启动,驶过道口。如果是第一种情况,那很好办,那第二种呢?时间就这么浪过去了,假如你非常不走运,那你的程序就会卡在停止-回滚-热启动的过程中。上面猜的过程就是分支预测。虽然是猜,但编译器也不是随便乱猜,那怎么猜呢?答案是分析之前的运行记录。假设之前很多次都是true,那这次就猜true,如果最近连续很多次都是false,那这次就猜false。但这一切都要看你的CPU了,因此,一般把容易成立的条件写在前面判断,把不容易成立的条件放在else那里 三目运算符 三目运算符,又称条件运算符,是计算机语言(c,c++,java等)的重要组成部分。它是唯一有3个操作数的运算符,所以有时又称为三元运算符。一般来说,三目运算符的结合性是右结合的。 <表达式1> ? <表达式2> : <表达式3>; "?"运算符的含义是:先求表达式1的值,如果为真,则执行表达式2,并返回表达式2的结果;如果表达式1的值为假,则执行表达式3,并返回表达式3的结果。 可以理解为条件 ? 结果1 : 结果2 里面的?号是格式要求。也可以理解为条件是否成立,条件成立为结果1,否则为结果2。 例如 int a=read(); if(a&1)puts("odd"); else puts("even"); 等价于 int a=read(); (a&1)?puts("odd"):puts("even"); 在代码的实现中,对于很多的if和else,可以三目套一个三目 int a=read(); if(a>0){ if(a&1)puts("odd"); else puts("even"); } else{ if(a&1)puts("ODD"); else puts("EVEN"); } 此代码等价于 int a=read(); (a>0)?((a&1)?puts("odd"):puts("even")):((a&1)?puts("ODD"):puts("EVEN")); 短路运算符 我们知道&&和||是两个短路运算符,什么叫短路运算符,就是一旦可以确定了表达式的真假值时候,就直接返回真假值了,比如下面代码 int a=read(); (a&1)&&puts("odd"); (a&1)||puts("even"); } 因为&&运算符号表示两者都满足当左边为真的时候就判断右边是否为真(就运行右边)否则因为左边为假就不运行右边(因为右边无论是否为真的无法让整个为真) ||同理 左边为假,就调用右边否则就不运行右边 因此可以把它给合起来 int a=read(); ((a&1)&&!puts("odd"))||puts("even"); 所以 if(A) B; → (A)&&(B) if(A) B; else C; → A&&(B,1)||C 但这些并不是短路运算符的精髓,短路运算符的精髓不仅在于优化时间,更是可以防止程序出错。 double t = rand(); if (t / RAND_MAX < 0.2 && t != 0) printf ("%d", t); double t = rand(); if (t != 0 && t / RAND_MAX < 0.2) printf ("%d", t); 这两种判断,谁快谁慢。但对于CPU来说很有区别。第一段代码中的t/RAND_MAX<0.2为true的概率约为 20%,但t!=0为true的概率约为1/RAND_MAX​​,明显小于20% 因此,如果把计算一个不含逻辑运算符布尔表达式的计算次数设为 1 次,设计算了 X 次,则对于第 1 段代码,X 的数学期望为 6/5​​ 次,但对于第二段代码,X 的数学期望2*(RAND_MAX-1) / RAND_MAX为 ,远远大于第一段代码。 不仅不同位置会优化时间,更是会防止程序错误,例如kuangbin搜索专题有题是Catch the Cow,就是搜索,不过判断走没走过得判断vis[n]和n < 1e6,我最最开始写的vis[n] && n < 1e6,提交上去RE了,看了很久才发现是这里的原因,得先判断n < 1e6,再做下一步操作。 所以, 遇到A&&B时,优先把可能为false的表达式放在前面。遇到A||B时,优先把可能为true的表达式放在前面。但也不一定是绝对这样,还得结合题目。 个人经验 我就得这样的优化主要还是在确保程序准确无误的时候再加上因为万一用了这个毒瘤了(特别是新手对变成不太熟悉,极容易出错) 其实不如在考虑一下剪枝吧!一些重复的结果被剪掉后会大大的减小时间而这种骚操作只会减掉几毫秒或几十毫秒 希望能对大家有用!
6 回复
分享
发布于 2019-11-05 14:47
有好多种情况吧。 就比如我如果满足A==B就执行下面的一堆操作。 if (A == B) {     Option1() ;     Option2() ;     Option3() ; } 你会发现你有一个大括号。那么这个时候你显然可以写成这样: if (A != B) continue ; Option1() ; Option2() ; Option3() ; 再比如如果你的if是嵌套在for里面,并且一旦这个if成立那么就会直接跳出循环,像这样: for (int i = 1 ; i <= N ; i ++) {     if (A == B) break ;     else Option() ; } 那么你如果知道for的特性,就可以把它写成这样: for (int i = 1 ; i <= N, A != B ; i ++)     Option() ; 如果你有一大堆条件判断语句,你可以尝试进行容斥,将之缩减为一个或者几个。 至于楼主说的有可能是全局类型的优化,那么就是一种算法策略上的东西了。这个东西应该是需要你在执行主体算法之前就做好一定的预处理,使我们我们的程序本身便会少走弯路,并不用使用很多的判断去避免冗余或者是其他情况,这可以象征性地理解为深搜里面的剪枝。 至于码风上面的问题我基本上没有什么好说的,但是我习惯性的会把if括号后面的else打一个tab if (A == B) {     Option1() ; Option2() ;     Option3() ; Option4() ; }    else if (A == C){     Option5() ; Option6() ;     Option7() ; Option8() ; }    else {     ... } 有人说我代码很毒....但是我确实觉得这样挺好看的呀。(无辜 当然你想用switch也可以,但是我觉得switch更丑...... 当然,我并不觉得刻意省略if/else有什么必要,条件选择语句可是基本语句之一诶,在美化程序的前提下是你的代码能够跑出来正确的结果......
3 回复
分享
发布于 2019-11-05 14:20
联易融
校招火热招聘中
官网直投
得先搞定写ifelse的人。如果离职了好办,上卫语句,策略模式balabala,如果没离职……参考三十六计,第一计,_为上记。
1 回复
分享
发布于 2019-11-05 11:41
我写代码有一个小技巧。 先把所有的异常统统return掉, 然后再处理正常的逻辑。另外,在循环中善用continue,先判断异常continue掉再处理。 比如有这样一个结构的函数 void f() { if (cond1) { for(xxx;xxx;xxx) { if (cond2) { // do you want; } } } } 那么我们可以改写为: void f() { if (!cond1) { return; } for (xxx;xxx;xxx) { if (!cond2) { continue; } // do you want } }
1 回复
分享
发布于 2019-11-05 12:00
void abc(...) {     if(...)     {         ...         return;     }     if(...)     {         ...         return;     }     if(...)     {         ...         return;     }     ...     return; } return的特性 在程序中调用即可
1 回复
分享
发布于 2019-11-05 14:37
首先,让我们排除switch case🤔
点赞 回复
分享
发布于 2019-11-05 11:21
记得有个设计模式可以解决
点赞 回复
分享
发布于 2019-11-05 11:28
switch case
点赞 回复
分享
发布于 2019-11-05 11:50
策略模式
点赞 回复
分享
发布于 2019-11-05 13:55
#define if 如果#define else 那么这样你的代码里就不会再出现任何的if else了
点赞 回复
分享
发布于 2019-11-05 14:37
可以考虑把否的判断提出来
点赞 回复
分享
发布于 2019-11-05 14:41
策略模式,工厂模式、枚举单例模式。将else代码放在函数前面,尽早返回
点赞 回复
分享
发布于 2019-11-05 17:46

相关推荐

2 7 评论
分享
牛客网
牛客企业服务