if-else、switch、while、for

文章:if else,switch,while,for颠覆你的编程认知

 

文章主要会涉及如下几个问题:

  1. if-elseswitch-case 两者相比谁的效率会高些?在日常开发中该如何抉择?
  2. 如何基于赫夫曼树结构减少 if-else 分支判断次数?
  3. 如何巧妙的应用 do...while(0) 改善代码结构?
  4. 哨兵是什么东西?如何利用哨兵提高有序数组查找效率?
  5. 如何降低 for 循环嵌套的时间复杂度?
  6. 如何利用策略模式替换繁琐的 if-else 分支?

 

一、if-else 和 switch-case 效率问题

switch 与 if-else 的效率问题

 

二、用 do-while(0) 改善代码结构

先看一段代码,要重点注意代码中的注释。

- (NSString *)handleString:(NSString *)str
{
    if (![str isKindOfClass:[NSString class]]) {
        return nil;
    }
    if(str.length <= 0) {
        return nil;
    }
    // 第一部分逻辑依赖于前面的判断,只有判断通过的时候才执行
    code1...code1
     
    // 第二部分逻辑不依赖于前面的判断(第二部分中的逻辑可能会依赖第一部分逻辑处理结果),无论判断是否通过都要执行
    code2...code2
}

试问,怎样做才能巧妙的满足上述注释代码的需求,因为上述代码中存在 return nil,一旦执行到此处,逻辑一和逻辑二处的伪代码都不会再执行。为了满足上述要求,我们可以巧妙的利用 break 退出临时构造的代码块,但不退出整个函数。

- (NSString *)handleString:(NSString *)str {
    do {
        if (![str isKindOfClass:[NSString class]]) {
            break;
        }
        if(str.length <= 0) {
            break;
        }
        // 第一部分逻辑依赖于前面的判断,只有判断通过的时候才执行
        code1...code2
    } while (0);    
    
    // 第二部分逻辑不依赖于前面的判断(第二部分中的逻辑可能会依赖第一部分逻辑处理结果),无论判断是否通过都要执行
    code2...code2
}

 

三、有序数组查找操作中的哨兵

正常的查找处理。

    NSArray *arr = @[@1, @2, @3, @4, @5];
    for (NSInteger i = 0; i < arr.count; i++) {
        if ([arr[i] integerValue] == 2) {
            NSLog(@"for 找到了");
        }
    }

利用哨兵进行查找处理。

- (BOOL)search:(NSNumber *)key array:(NSMutableArray *)arr
{
    if (arr.count <= 0) {
        return NO;
    }

    NSNumber * firstObj = (NSNumber *)arr[0];
    if ([firstObj integerValue] == [key integerValue]) {
        return YES;
    }

    NSInteger i = arr.count - 1;
    NSLock * lock = [[NSLock alloc]init];
    [lock lock];
    arr[0] = key;
    // 同上面 for 循环相比,i < arr.count 的判断,在处理大批量数据时候,对性能提升比较大
    while ([arr[i] integerValue] != [key integerValue]) {
        i--;
    }
    arr[0] = firstObj;
    [lock unlock];

    return (i != 0);
}

仔细观察上述两段代码,同样是在有序数组中查找目标为 2 的元素,第一段代码是常规迭代处理,第二段代码是将要查找的元素设置为哨兵。同第一段代码相比第二种方式少了 i < arr.count 的判断,在小批量有序数组查询中对效率的提升并无明显影响,但是在处理大批量数据时候,对性能提升还是比较明显的。

 

四、多层 for 嵌套处理

实际开发中应尽量避免使用双层 for 循环,客户端数据量比较小可能实际开发中并不是很注意这些。但是后端开发过程中,数据量比较大, 为了提升性能,有些公司后端开发中可能会直接规定避免使用多层 for 循环嵌套的形式。一般第二层或更深层的 for 循环可以使用字典替换。双层 for 循环嵌套的时间复杂度是 n 的二次方。但如果内部 for 循环用字典代替时间复杂度为 O(2n)(实际是 O(n))。如:两个数组中有且只有一个相同元素,寻找该元素。其中一个数组就可以先用字典做保存,遍历第一个数组的时候,同字典中的数据做比较即可。

    NSArray *arr1 = @[@1, @2, @3, @4, @5];
    NSArray *arr2 = @[@5, @6, @7, @8];
    NSMutableDictionary * dict = [NSMutableDictionary dictionary];
    for (NSInteger i = 0; i < arr2.count; i++) {
        [dict setObject:arr2[i] forKey:[NSString stringWithFormat:@"%ld", i]];
    }

    for (NSInteger i= 0 ; i < arr1.count; i++) {
        NSNumber * number = [dict objectForKey:[NSString stringWithFormat:@"%ld", i]];
        if ([arr1[i] integerValue] == [number integerValue]) {
            NSLog(@"相同的数据为:%@", number);
            break;
        }   
    }

 

五、用策略模式替换 if-else

https://www.jianshu.com/p/98fa80eebc52

You may also like...