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

本文介绍了一种高效地翻转英文句子中单词顺序的方法,包括四种不同的思路和对应的C/C++代码实现。重点是通过从后往前遍历字符串,逐个将单词翻转并插入到正确位置,从而达到翻转整个句子的目的。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

输入一个英文句子,翻转句子中单词的顺序,要求单词内字符的顺序不变,句子中单词以空格隔开,为简单起见,标点符号和普通字母一样处理。例如:输入“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*,这样在指针加的时候才会保证每次加一个字节

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值