一步一步写算法(之字符串查找 中篇)

原贴地址:http://blog.csdn.net/feixiaoxing/article/details/6911730

【 声明:版权所有,欢迎转载,请勿用于商业用途。  联系信箱:feixiaoxing @163.com】


    昨天我们编写了简单的字符查找函数。虽然比较简单,但是也算能用。然而,经过我们仔细分析研究一下,这么一个简单的函数还是有改进的空间的。在什么地方改进呢?大家可以慢慢往下看。

    下面的代码是优化前的代码,现在再贴一次,这样分析起来也方便些:

[cpp]  view plain copy
  1. char* strstr(const char* str, char* data)  
  2. {  
  3.     int index;  
  4.     int len;  
  5.   
  6.     if(NULL == str || NULL == str)  
  7.         return NULL;  
  8.   
  9.     len = strlen(data);  
  10.     while(*str && (int)strlen(str) >= len){  
  11.         for(index = 0; index < len; index ++){  
  12.             if(str[index] != data[index])  
  13.                 break;  
  14.         }  
  15.   
  16.         if(index == len)  
  17.             return (char*) str;  
  18.   
  19.         str++;  
  20.     }  
  21.   
  22.     return NULL;  
  23. }  
     不知道朋友们发现没有,原来的while条件中有一个很费时的操作。那就是每次str移动的时候,都需要判断str的长度大小。如果str的长度远大于data的长度,那么计算str长度的时间是相当可观的。

[cpp]  view plain copy
  1. int check_length_of_str(const char* str, int len)  
  2. {  
  3.     int index;  
  4.   
  5.     for(index = 0; index < len; index ++){  
  6.         if('\0' == str[index])  
  7.             return 0;  
  8.     }  
  9.   
  10.     return 1;  
  11. }  
  12.   
  13. char* strstr(const char* str, char* data)  
  14. {  
  15.     int index;  
  16.     int len;  
  17.   
  18.     if(NULL == str || NULL == str)  
  19.         return NULL;  
  20.   
  21.     len = strlen(data);  
  22.     while(*str && check_length_of_str(str, len)){  
  23.         for(index = 0; index < len; index ++){  
  24.             if(str[index] != data[index])  
  25.                 break;  
  26.         }  
  27.   
  28.         if(index == len)  
  29.             return (char*) str;  
  30.   
  31.         str++;  
  32.     }  
  33.   
  34.     return NULL;  
  35. }  
    上面的代码很好地解决了长度判断的问题,这样一来每次比较的长度很短,只要判断len的大小字符长度即可。但是,我们还不是很满足,如果两者不比较岂不更好。那么,有没有这个可能?我们发现,如果str在每次比较不成功的时候,就会自己递增一位。那么我们只要判断这一位是不是‘\0’不就可以了吗?所以说,我们的代码还可以写成下面的形式。

[cpp]  view plain copy
  1. char* strstr(const char* str, char* data)  
  2. {  
  3.     int index;  
  4.     int len;  
  5.   
  6.     if(NULL == str || NULL == str)  
  7.         return NULL;  
  8.   
  9.     len = strlen(data);  
  10.     if((int)strlen(str) < len)  
  11.         return NULL;  
  12.   
  13.     while(*str){  
  14.         for(index = 0; index < len; index ++){  
  15.             if(str[index] != data[index])  
  16.                 break;  
  17.         }  
  18.   
  19.         if(index == len)  
  20.             return (char*) str;  
  21.   
  22.         if('\0' == str[len])  
  23.             break;  
  24.   
  25.         str++;  
  26.     }  
  27.   
  28.     return NULL;  
  29. }  
    和上面第一次的优化不同,我们在进入while之前会判断两者的长度区别,但是经过第一次判断之后,我们就再也不用判断了,因为接下来我们只要判第n个元素是否为‘\0’即可,原来的n-1个元素我们已经判断过了,肯定是合法的元素。为什么呢?大家可以好好想想。


(二)、KMP算法

    KMP算法本质上说是为了消除查找中的多余查找步骤。怎么就产生了多余的查找步骤了呢。我们可以用示例说话。假设有下面两个字符串:

    A:  baaaaabcd

    B:  aaaab

    那么这两个查找的时候会发生什么现象呢?我们可以看一下:

[cpp]  view plain copy
  1. /*      1 2 3 4 5 6 7 8 9 
  2. *    A: b a a a a a b c d 
  3. *    B:   a a a a b 
  4. *       1 2 3 4 5 6 7 8 9 
  5. */    
    我们发现B和A在从第2个元素开始比较的时候,发现最后一个元素是不同的,A的第6个元素是a,而B的第5个元素是b。按照普通字符串查找的算法,那么下面A会继续向右移动一位,但是事实上2-5的字符我们都已经比较过了,而且2-5这4个元素正好和B的前4个元素对应。这个时候B应该用最后一位元素和A的第7位元素比较即可。如果这个计算步骤能省下,查找的速度不就能提高了吗?


【预告: 下面一篇博客介绍KMP的编写和多核查找算法】

    



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值