1. 程式人生 > >單詞翻轉(4種思路,C/C++程式碼)

單詞翻轉(4種思路,C/C++程式碼)

輸入一個英文句子,翻轉句子中單詞的順序,要求單詞內字元的順序不變,句子中單詞以空格隔開,為簡單起見,標點符號和普通字母一樣處理。例如:輸入“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*,這樣在指標加的時候才會保證每次加一個位元組