您的位置:首页 > 编程语言 > C语言/C++

单词翻转(4种思路,C/C++代码)

2016-05-19 16:08 323 查看
输入一个英文句子,翻转句子中单词的顺序,要求单词内字符的顺序不变,句子中单词以空格隔开,为简单起见,标点符号和普通字母一样处理。例如:输入“I am a student.”则输出:“student. a am I”。

思路一:最后一个单词的位置是不用移动的。从后面往前面遍历,遇到第一个空格时,开始统计下一个单词的长度n,统计完成后将该单词后面的单词向前移动n位,并将该单词移动到字符串的末尾;依照这样的方式,直至遍历完整个字符串。

评:该方法的实现过程异常复杂,时间复杂度太高。

思路二:从后往前依次遍历源字符串src,每次遍历完一个单词后,直接将该单词整个拷贝到另一个字符串dst中,依次遍历原字符串,分别将每个独立的单词拷贝到dst中。

评:该算法的空间复杂度比较高,因为需要多申请一段空间dst来保存遍历的结果。

思路三:将整个字符串翻转,然后分别将字符串中的单个单词独立进行翻转。

思路四:三步反转法:先将每个单词分成独立的几部分,然后分别对它们进行翻转,返回将整个字符串进行翻转。(最后一步的翻转其实是可以省略的,直接将字符串从后往前输出即可)


评:思路三和四的思想是一样的,个人更喜欢第四种。

    输入:“I am a student.”

中间结果:“I ma a .tneduts”

    输出:“student. a am I”

C/C++代码


//输入“I am a student.”则输出:“student. a am I”。
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <string.h>

using namespace std;

void *reverse(char *src, char *dst)
{
char *p1, *p2;
if(src == NULL || dst == NULL)
{
return NULL;
}
//从src的最后一个字符开始遍历
p1 = src + strlen(src) - 1;
p2 = p1;
while (p1 != src)
{
if (*p1 == ' ')
{
int len = p2 - p1;//单词的长度
memcpy(dst, p1 + 1, len);
//每个单词的末尾加上一个空格
dst += len;
*dst++ = ' ';
p1--;
p2 = p1;
}
else
{
//不断将p1向前移动
p1--;
}
}
//最后一次拷贝单词
int len = p2 - p1 + 1;
memcpy(dst, p1, len);
dst += len;
*dst++ ='\0';

}
void print(char *s, int m)
{
for (int i = 0; i < m; i++)
{
if (s[i] == ' ')
cout << " ";
else
cout << s[i];
}
cout << endl;
}
int main()
{
char *dst;
dst = (char*)malloc(sizeof(char) * 10);
char a[] = "I am a student.";
//单词的长度
int n = strlen(a);
cout << "n=" << n << endl;
//显示未翻转前的字符串
print(a, n);
//单词翻转
reverse(a, dst);
//显示翻转之后的字符串
print(dst, n);

return 0;
}
//三步反转法
#include"stdafx.h"
#include<iostream>

using namespace std;

void print(char *s, int m)
{
for (int i = 0; i < m; i++)
{
cout << s[i];
}
cout << endl;
}

//将每个单词进行翻转
void reverse(char *s,int low,int high)
{
while (low < high)
{
int tmp = s[high];
s[high] = s[low];
s[low] = tmp;
low++;
high--;
}
}

int main()
{
int num = 0;
int low, high;
//cout << "请输入一个字符串:";
char a[] = "I am a student.";
//单词的长度
int n = strlen(a);
cout << "n=" << n << endl;
//显示未翻转前的字符串
print(a, n);
//将字符串分为独立的几个单词,并分别进行翻转
for (int i = 0; i <= n; i++)
{
if (a[i] == ' '||a[i]=='\0')
{
//单词翻转
reverse(a,i-num,i-1);
num = 0;
}
else
{
num++;
}
}
//中间结果
print(a, n);
//显示翻转之后的字符串
for (int i = n-1; i >=0; i--)
{
cout << a[i];
}
cout << endl;

return 0;
}

附:

memcpy 函数用于把资源内存(src所指向的内存区域)拷贝到目标内存(dest所指向的内存区域);拷贝多少个?有一个count变量控制拷贝的字节数;
函数原型:void *memcpy(void *dest, void *src, unsigned int count);
用法:可以拷贝任何类型的对象,因为函数的参数类型是void*(未定义类型指针),也就是说传进去的实参可以是int*,short*,char*等等;但是由于函数拷贝的过程是一个字节一个字节的拷贝的,所以实际操作的时候要把void*强制转化为char*,这样在指针加的时候才会保证每次加一个字节。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  单词翻转