注意逆序和逆序输出是两个概念。
若只是逆序输出则有很多种方法,最简单的就是,利用C语言中的字符指针。先将指针通过++移到末尾,再--往前移动同时打印输出。
下面主要讨论如何实现逆序
分析:对一个数据进行某种操作,然后进行这种操作的逆操作可以还原到本身。所以实现方法是有多种的。以二进制操作速度最快。这里采用C中的指针概念。
#include <stdio.h>
#include <string.h>
void reverse(char *s)
{
int i = 0;
int len = strlen(s);
int j = len-1;
while(i < j)
{
s[i] ^= s[j] ^= s[i] ^= s[j];
i++;
j--;
}
}
int main(void)
{
char str[] = "abcd";
printf("%s\n",str);
reverse(str);
printf("%s\n",str);
return 0;
}
代码解释,其中的位运算使用了^=相当于
s[i] = s[i]^s[j];
s[j] = s[i]^s[j];
s[i] = s[i]^s[j];
这里^是异或运算符。解释如下
参与运算的两个值,如果两个相应位相同,则结果为0,否则为1。即:0^0=0, 1^0=1,0^1=1, 1^1=0
比如:
int x=7,y=8;
x=x^y;
y=x^y;
x=x^y;
结果x=8,y=7;
就如同
int x=7,y=8;
x=x+y;
y=x-y;
x=x-y;
实际原理就是数字A异或B两次,就得到A。而B被A异或两次,就得到B。
顺便提一下一个常见错误,在java中实现时,有些人认为以下也实现了需求,但其忽视了String类的不可变性。
public class StringReverseWithoutExtraSpace {
public static String reverse(String s) {
char[] str = s.toCharArray();
int begin = 0;
int end = s.length() - 1;
while (begin < end) {
str[begin] = (char) (str[begin] ^ str[end]);
str[end] = (char) (str[begin] ^ str[end]);
str[begin] = (char) (str[end] ^ str[begin]);
begin++;
end--;
}
System.out.println(str);//这里实际上打印的是字符数组
return new String(str); //若要把逆序结果保留则必须new一个新的字符串对象。因为String具有不可变性。
}
public static void main(String[] args) {
String str = "abcd";
System.out.println(str);
reverse(str);
System.out.println(str);
}
}
打印结果
abcd
dcba
abcd
贴上toCharArray源码:
/**
* Converts this string to a new character array.
*
* @return a newly allocated character array whose length is the length
* of this string and whose contents are initialized to contain
* the character sequence represented by this string.
*/
public char[] toCharArray() {
// Cannot use Arrays.copyOf because of class initialization order issues
char result[] = new char[value.length];
System.arraycopy(value, 0, result, 0, value.length);
return result;
}
可以发现实际上创建了新空间即使字符数组。