前面已经在《字符串逆序算法实现》这篇文章中介绍了如何实现字符串逆序输出算法的实现,本文将在该基础上加深一点难度介绍字符串按单词逆序输出的算法,并给出C语言与Java语言两个版本算法的实现。
字符串按单词逆序输出的要求是将给定的字符串按单词逆序输出,但单词内部按正常顺序输出。例如,给定字符串“I am a student”按单词逆序输出为“student a am I”。在《字符串逆序算法实现》这篇文章中是通过两个指向字符串首尾的指针先分别交换各自指针所指向的元素,然后前指针向后移动,后指针向前移动。但在本算法中如果直接这样逆序的话肯定是不行的。分析发现直接将整个字符串逆序的话,所有单词的位置是逆序了,但每个单词的内容也跟着逆序了,显然这样是不正确的,因此可以采用先每个单词内部逆序,然后再整个字符串逆序(或者先整个字符串逆序,然后再每个单词逆序)。在这里可以以空格符作为每个单词区分的标识符,并注意最后一个单词的逆序问题即可实现。
例如,对于字符串I am a student”采用先单词内部局部逆序,字符串变为"I ma a tneduts",然后再将整个字符串逆序得到最终字符串变为“student a am I”。采用先整个字符串逆序,再每个单词内部局部逆序亦可以得到类似的分析结果。
下面给出字符串按单词逆序算法的C语言版本:
<span style="font-size:18px;"><span style="font-size:18px;">#include <stdio.h>
#include <stdlib.h>
void ReverseWord(char *front,char *end)
{
while(front<end)
{
char temp=*front;
*front++=*end;
*end--=temp;
}
}
char * Reverse(char *s)
{
char *pre=s;
char *current=s;
while(*current!='\0')
{
if(*current==' ')
{
ReverseWord(pre,current-1);
current++;
pre=current;
}
else
{
current++;
}
}
ReverseWord(pre,current-1);
ReverseWord(s,current-1);
return s;
}
int main(int argc, char *argv[])
{
char a[]="how are you ?";
printf("原始字符串:%s\n",a);
printf("逆序之后的字符串:%s\n",Reverse(a));
return 0;
}</span></span>
以上算法并不难,在此需要注意的地方是关于C语言中函数参数传递的问题。在C语言中函数参数传递有2种方式-值传递和指针传递。
(1)值传递
在C语言中进行值传递时,是将实参中的值赋值给形参,而实参与形参并不是同一存储单元,所以函数调用后实参中的值并没有发生变化。
(2)指针传递
在C语言中进行指针传递时,形参是指针变量,实参是一个变量的地址,调用函数时形参指向的是实参变量的地址,这种传递方式还是“值传递”,形参与实参并不是同一存储单元,但由于形参指向的是实参变量的地址,所以调用函数时在函数中改变的不是实参的值,而是实参地址所指向的变量值。
因此,在上面C语言代码中的if代码块会发现传入ReverseWord函数是2个指针,pre指针指向当前所遇到单词开始的位置,(current-1)指针指向当前单词结束的位置,在ReverseWord函数通过2个形参指针参数接收2个实参指针参数,
<span style="font-size:18px;"><span style="font-size:18px;"> if(*current==' ')
{
ReverseWord(pre,current-1);
current++;
pre=current;
}</span></span>
并在ReverseWord函数中形参指针变量指向实参指针变量所指向的变量存储单元,通过移动形参指针变量实现单词内部局部的逆序,但此时在ReverseWord函数调用结束后实参指针变量pre指针仍然指向当前所遇到单词开始的位置,实参指针变量(current-1)指针仍然指向当前单词结束的位置,只不过通过ReverseWord函数形参指针变量所指向存储单元中的内容已经发生了变化,所以才有了下面current++和pre=current操作,确保pre指针指向下一个单词开始的位置。
下面再给出字符串按单词逆序算法的Java版实现:
<span style="font-size:18px;"><span style="font-size:18px;">public class StrReverse {
private void ReverseWord(char[] a,int front,int end)
{
while(front<end){
char temp=a[front];
a[front]=a[end];
a[end]=temp;
front++;
end--;
}
}
private String Reverse(String s)
{
char[] a=s.toCharArray();
int pre=0,current=0;
while(current<a.length)
{
if(a[current]==' ')
{
ReverseWord(a,pre,current-1);
current++;
pre=current;
}else{
current++;
}
}
ReverseWord(a,pre,current-1);
ReverseWord(a,0,current-1);
return new String(a);
}
public static void main(String[] args) {
String str="how are you";
System.out.println("原字符串为:"+str);
System.out.println("逆序后的字符串为:"+new StrReverse().Reverse(str));
}
}
</span></span>
Java版的算法实现与C语言版的算法实现思路是一样的,在Java版算法实现中需呀注意以下几点:
1、Java语言中函数参数的传递方式有2中:值传递和应用传递。在Java语言中,原始数据类型在传递函数参数是按值传递,包装类型在传递函数参数时都是按引用传递的;即Java在处理8种基本数据类型的传递时都是采用值传递,而其它所有类型的参数传递都是采用引用传递的。
2、在Java中访问类中的方法有这几种方法:(1)通过实例对象访问,即通过”实例对象名.方法名“访问;(2)将类中方法用static定义为静态方法,通过类名直接访问,即通过"类名.方法名"方法访问。