代码改变世界

字符串逆序总结

2013-08-02 21:00  youxin  阅读(793)  评论(0编辑  收藏  举报

对一个字符串求逆序,常用方法:

void reverse1(char *s)
{
    
    int len=strlen(s);
    char *p=s;//p指向首字符
    char *q=s+len-1;//q指向最后一个字符
    while(q>p)
    {
        char tmp=*q;*q=*p;*p=tmp;
        q--;
        p++;
    }
}

用递归的方式,需要给定逆序的区间,调用方法:Reverse(s, 0, strlen(s))

// 对字符串s在区间left和right之间进行逆序,递归法
void Reverse( char* s, int left, int right )
{
    if(left >= right)
        return s ;

    char t = s[left] ;
    s[left] = s[right] ;
    s[right] = t ;

    Reverse(s, left + 1, right - 1) ;
}

三 非递归法,同样指定逆序区间,和方法一没有本质区别,一个使用指针,一个使用下标。

// 对字符串str在区间left和right之间进行逆序
char* Reverse( char* s, int left, int right )
{
    while( left < right )
    {
        char t = s[left] ;
        s[left++] = s[right] ;
        s[right--] = t ;
    }

    return s ;
}

逆序打印:

还有一类题目是要求逆序输出,而不要求真正的逆序存储。这题很简单,有下面几种方法,有的方法效率不高,这里仅是提供一个思路而已。

先求出字符串长度,然后反向遍历即可。

void ReversePrint(const char* s)
{
    int len = strlen(s) ;
    for (int i = len 1; i >= 0--i)
        cout 
<< s[i];
}

如果不想求字符串的长度,可以先遍历到末尾,然后在遍历回来,这要借助字符串的结束符'\0

复制代码
void ReversePrint(const char* s)
{
    const char* p = s ;

    while (*p)
        *p++ ;

    --p ; //while结束时,p指向'\0',这里让p指向最后一个字符

    while (p >= s)
    {
        cout <<*p ;
        --p ;
    }
}
复制代码

对于上面第二种方法,也可以使用递归的方式完成。

void ReversePrint(const char* s)
{
    if(*(s +1!= '\0')
        ReversePrint(s 
1) ;
    cout 
<< *s ;
}

我自己写的:

void reverse(char *s)
{
    if(*s=='\0')
    {
        return;
    }
    else
    {
        func(s+1);
        cout<<*s;
    }
}

注意,当s为字符串的指针使,cout<<s会输出整个字符串,我最开始

写成cout<<s 就错了。

 按单词逆序:

给定一个字符串,按单词将该字符串逆序,比如给定"This is a sentence",则输出是"sentence a is This",为了简化问题,字符串中不包含标点符号。

分两步

1 先按单词逆序得到"sihT si a ecnetnes"

2 再整个句子逆序得到"sentence a is This"

对于步骤一,关键是如何确定单词,这里以空格为单词的分界。当找到一个单词后,就可以使用上面讲过的方法将这个单词进行逆序,当所有的单词都逆序以后,将整个句子看做一个整体(即一个大的包含空格的单词)再逆序一次即可,如下图所示,第一行是原始字符换,第二行是按单词逆序后的字符串,最后一行是按整个句子逆序后的字符串。

// 对指针p和q之间的所有字符逆序
void ReverseWord(char* p, char* q)
{
    while(p < q)
    {
        char t = *p ;
        *p++ = *q ;
        *q-- = t ;
    }
}

// 将句子按单词逆序
char* ReverseSentence(char* s)
{
    // 这两个指针用来确定一个单词的首尾边界
    char* p = s ; // 指向单词的首字符
    char* q = s ; // 指向空格或者 '\0'

    while(*q != '\0')
    {
        if (*q == '')
        {
            ReverseWord(p, q - 1) ;
            q++ ; // 指向下一个单词首字符
            p = q ;
        }
        else
            q++ ;
    }

    ReverseWord(p, q - 1) ; // 对最后一个单词逆序
    ReverseWord(s, q - 1) ; // 对整个句子逆序

    return s ;
}
int main()
{
///    string s;
//    cin>>s;
    char s[100];
    gets(s);
    cout<<strlen(s)<<endl;
    ReverseSentence(s);
    cout<<s<<endl;
}

注意gets(s),最开始我用的是scanf("%s",s);发现输入this is.strlen(s)为4.原因是scanf忽略空格和换行符。gets则可以接受换行符。

char string[15]; gets(string); /*遇到回车认为输入结束*/

scanf("%s",string); /*遇到空格认为输入结束*/

所以在输入的字符串中包含空格时,应该使用gets输入。

leetcode题目:https://oj.leetcode.com/problems/reverse-words-in-a-string/

Given an input string, reverse the string word by word.

For example,
Given s = "the sky is blue",
return "blue is sky the".

 

Clarification:
  • What constitutes a word?
    A sequence of non-space characters constitutes a word.
  • Could the input string contain leading or trailing spaces?
    Yes. However, your reversed string should not contain leading or trailing spaces.
  • How about multiple spaces between two words?
    Reduce them to a single space in the reversed string.
void reverseWords(string &s)
  {
    string rs;
    for (int i = s.length()-1; i >= 0; )
    {
      while (i >= 0 && s[i] == ' ') i--;
      if (i < 0) break;
      if (!rs.empty()) rs.push_back(' ');
      string t;
      while (i >= 0 && s[i] != ' ') t.push_back(s[i--]);
      reverse(t.begin(), t.end());
      rs.append(t);
    }
    s = rs;
  }

更多:http://www.2cto.com/kf/201403/286602.html

参考:http://www.cnblogs.com/graphics/archive/2011/03/09/1977717.html