C/C++面试之算法系列--以单词为最小单位翻转字符串

以单词为最小单位翻转字符串

Sailor_forever sailing_9806@163.com 转载请注明

http://blog.csdn.net/sailor_8318/archive/2007/09/10/1778566.aspx

 

××××××××××××××××××××××××××××

 write the function string reversestringwordbyword(string input) that reverses a string word by word.  for instance,
  reversestringwordbyword('the house is blue') --> 'blue is house the'
  reversestringwordbyword('zed is dead') --> 'dead is zed'
  reversestringwordbyword('all-in-one') --> 'all-in-one'

 

××××××××××××××××××××××××××××

算法一 递归方式,递归寻找最后一个单词,将其拷贝到des返回拷贝后的des指针,供上层调用继续拷贝其前面的单词,依次类推,最后拷贝完整个字符串

char *reverse_str_word_by_word(char *des, char *src)

{

    char   *p1 = src;

       int length;

 

    if ((NULL == des) || (NULL == src))

        return NULL;

 

    while (*p1)

    {

              //length = p1-src; // error for the last word

 

              if (' ' == *p1)

        {    

                     // the new src is p1+1 except ' '

                     des = reverse_str_word_by_word(des,p1+1);

                     // overwrite the previous '/0' by ' ' to save another word

                     *des++ = ' ';

                    

            memcpy(des, src, length);

                     *(des+length) = '/0';   // in case it is the end

 

           return des+length;

        }

              p1++;

              length = p1-src;

    }

       //this is the last word or only one word

       memcpy(des, src, length);

       *(des+length) = '/0';   // in case it is the end

      

       // return the initial revised dest addr

    return des+length;

}

××××××××××××××××××××××××××××

算法二 递归方式改进版,去掉了数组长度变量, 将最后一个单词和中间递归调用的拷贝单词整合到了一块,代码更简洁,但是第一种的递归退出和再调用条件更明确

 

char *reverse_str_word_by_word(char *des, char *src)

{

    char   *p1 = src;

 

    if ((NULL == des) || (NULL == src))

        return NULL;

 

       while (*p1)

    {

              if (' ' == *p1)

        {    

                     des = reverse_str_word_by_word(des,p1+1);

                     // overwrite the previous '/0' by ' ' to save another word

                     *des++ = ' ';

                     break;

        }

              p1++;

    }

       //this is the last word or for breaking

       memcpy(des, src, p1-src);

       des += p1-src;

       *des = '/0';   // in case it is the end

      

       // return the revised dest addr

    return des;

}

 

int main()

{

    char src1[]   = "zed is dead";

       char src2[] = "all-in-one";

    char src3[] = "the house is blue";

       char dst[30];

 

    reverse_str_word_by_word(dst,src1);

       printf("reverse_str_word_by_word of /"zed is dead/" is %s/n", dst);

 

       reverse_str_word_by_word(dst,src2);

       printf("reverse_str_word_by_word of /"all-in-one/" is %s/n", dst);

 

       reverse_str_word_by_word(dst,src3);

       printf("reverse_str_word_by_word of /"the house is blue/" is %s/n", dst);

   

    system("pause");

      

       return 0;

       //reverse_str_word_by_word of "zed is dead" is dead is zed

       //reverse_str_word_by_word of "all-in-one" is all-in-one

       //reverse_str_word_by_word of "the house is blue" is blue is house the

 

}

 

××××××××××××××××××××××××××××

算法三 传统算法,从后往前,依次拷贝,

 /*
 *  name: reverse_src_word_by_word
 *  params:
 *    des           [out]          
输出字符串, des 指向实现申请的空间

 *    src           [in]           
输入字符串,需要处理的字符串
 *  return:
 *   
处理完成后的 des 指针
 *  notes:
 *   
以单词为最下单位翻转字符串
 *  author: a.tng 2006/06/16 9:06
 */
char *reverse_str_word_by_word(char *des, char *src)
{
    char   *p1, *p2;
    char   *psz_dest;
    if ((null == des) || (null == src))
        return null;
    /*
src 的最后一个字符开始遍历 */
   
p1 = src + strlen(src) - 1;

    p2 = p1;
    psz_dest = des;
    while (p1 != src)
    {

if (' ' == *p1)
        {
            int n_len;
            /*
找到一个单词,拷贝单词
*/
            n_len = p2 - p1;
            memcpy(psz_dest, p1 + 1, n_len);
            psz_dest += n_len;
            *psz_dest++ = ' ';
            /*
准备寻找下一个单词 */
            p1--; p2 = p1;
        }
        else
        {
            /* p1
往前移一位
*/
            p1--;
        }
    }
   
/* 最后一次拷贝单词 */

    if (p1 != p2)
    {
        int n_len;
        n_len = p2 - p1 + 1;
        memcpy(psz_dest, p1, n_len);
        psz_dest += n_len;
        *psz_dest = '/0';
    }
    return des;
}

 

比较费空间,因为多申请了一段空间来保存结果

 

××××××××××××××××××××××××××××

算法四 整体翻转,每个单词局部翻转,多次利用字符串翻转

在看了其他高手的实现后,发现可以不用申请空间,并且循环的次数更少,也可以实现相同的效果。

原字符串: the house is blue
先翻转整个字符串
-> eulb si esuoh eht
再翻转单个单词


#define reverse_word(p1, p2) while (p1 <= p2) /
    { /
        char ch; /
        ch = *p1; *p1 = *p2; *p2 = ch; /
        p1++; p2--; /
    }
/*
 *  name: reverse_src_word_by_word
 *   
优化: 先翻转整个字符串,再翻转单个单词
 * *  author: a.tng 2006/06/16 10:37
 */

char * reverse_str_word_by_word2(char *src)
{
    char   *p1, *p2;
    int     n_src_len;
    if (null == src)
        return null;
    /*
先把整个字符串翻转一次
*/
    n_src_len = strlen(src);
    p1 = src; p2 = src + n_src_len - 1;
    reverse_word(p1, p2);
#if 0
    while (p1 <= p2)
    {
        /*
交换头字符和尾字符
*/
        char ch;
        ch = *p1; *p1 = *p2; *p2 = ch;
        p1++; p2--;
    }
#endif
    /*
再翻转单个单词
*/
    p1 = src; p2 = p1;
    while ('/0' != *p2)
    {
        if (' ' == *p2)
        {
            char   *p;
            p = p2 - 1;
            reverse_word(p1, p);
#if 0          
            while (p1 <= p)
            {
                char ch;
                ch = *p1; *p1 = *p; *p = ch;
                p1++; p--;
            }
#endif
            p2++;
            p1 = p2;
        }
        else
        {
            p2++;
        }
    }
    /*
翻转最后一个单词
*/
    p2--;
    reverse_word(p1, p2);
#if 0
    while (p1 <= p2)
    {
        char ch;
        ch = *p1; *p1 = *p2; *p2 = ch;

  p1++; p2--;
    }
#endif
    return src;
}

int main()
{
    // char src[] = ' all-in-one ';
    // char src[] = 'the house is blue';
    char    src[]   = 'zed is dead';
    (void) reverse_str_word_by_word2(src);
    printf('*****%s*****/n', src);
    system('pause');
}

参考资料:

http://blog.csdn.net/jiyucn/archive/2006/06/16/803059.aspx

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值