C编程从入门到实践
上QQ阅读APP看书,第一时间看更新

7.4 技术解惑

7.4.1 循环中的低效问题

先看下面的代码。

    for (I = 0; i <    strlen(str); I ++)
    //处理str[i];

请问这个循环的时间复杂度是多少?如果你的回答是On),那你就太粗心了,事实上它是O(n*n)。不要惊奇,事实上这个时间复杂度是在循环条件中调用strlen函数产生的。在C语言中我们经常用以’\0’为结尾字符的字符数组表示字符串,strlen就是求解用这种逻辑表示字符串的长度的,它的实现方法就是从第1个字符开始向后找,直到找到字符’\0’为止,它的复杂度为O(n),而对它的调用是在循环条件中,循环次数为n,条件会判断(n+1)次,因此说这段代码的时间复杂度为O(n*n)。

不要指望编译器能对代码进行优化从而把对strlen的调用提到循环以外,这是很难的,因为strlen不是一个简单的算术表达式而是一个函数调用,所以编译器不知道它是不是有副作用,如果有副作用,则一次调用和多次调用的结果是不一样的。因此编译器只好完全按照代码告诉它的逻辑多次执行strlen。

在一般情况下,较好的写法是:

    char * temp;
    for (temp = str; *temp ! = '\0'; temp ++)
    *temp  ...

接下来的代码如下。

    int slen = strlen(str);
    for(i = 0; i < slen; i    ++
    str[i]...

在大多数情况下,如果循环条件中有一个函数调用,那么它的返回值是不会在循环条件中改变的,一定要把它拿到循环外面来。