C语言实现字符串的左旋转

C语言实现字符串的左旋转

    下面采用C语言用三种方法实现这样一个问题:给定一个字符串如  abcdef 左旋转2位,即cdefab,左旋转6位,即abcdef。

   从上面的描述中大概得知这是一个周期性的字符串重现问题,具有周期性。下面采用三种方法实现该算法。

   第一种方法:在每一次的字符旋转中将后续的字符进行往前缩进的操作。即从前往后遍历每一个待旋转的字符,将当前字符后续的所有字符往前缩进一个位置,缩进完毕则把当前的字符填充至字符串的尾部。这种方法可以解决我以前遇到的这样的一个问题:每次进行字符串的操作之后,字符串中的字符位序将发生变化,即字符串的每一次操作是一种对字符串的动态操作。

   下面是代码:

#include <stdio.h>
#include <stdlib.h>

#define N 6

//第二种左旋转字符串的方法:关键在于抓住每一次的旋转的做的事情:即字符往前移动
char* RotateLeftTwo(char* strChar,int n,int k)
{
	char temp;
	//实际上旋转的位数
	k %= n;
	while (k--)
	{
		temp = strChar[0];
		for (int i=1;i<n;i++)
		{
			strChar[i-1] = strChar[i];
		}
		strChar[n-1] = temp;
	}
	return strChar;
}

int main(int argc, char **argv)
{
	char strChar[] = "abcdef";	
	int k;
	printf("输入旋转的位数: ");
	scanf("%d",&k);

	printf("原先的字符串: ");
	for (int i=0;i<N;i++)
	{
		printf("%c",strChar[i]);
	}
	printf("\n");

	char* strCharSec;
	strCharSec = RotateLeftTwo(strChar,N,k);
	printf("字符串左旋转%d位后的字符串: ",k);
	for (int j=0;j<N;j++)
	{
		printf("%c",strCharSec[j]);
	}
	printf("\n");
	
	return 0;
}

运行结果:




    第二种方法:寻找旋转之后前后字符串的位序关系,在草稿纸进行一番演示推导之后有这样的一种关系:



    其中i'表示旋转后的字符位序,i表示旋转前的字符位序,k表示旋转的位数,n表示字符串中总的字符个数

    代码如下:

#include <stdio.h>
#include <stdlib.h>

#define N 6

//第一种字符串左旋转的方法:核心在于找寻前后的字符串中的字符位序的关系
char* RotateLeftOne(char* strChar,int n,int k)
{
	char* RealChar;
	int ii;
	RealChar = (char*)(malloc(n*sizeof(char)));
	for (int i=0;i<n;i++)
	{
		//实际上旋转的位数以及对应的前后字符串字符的位序
		ii = (i-k+n)%n;
		RealChar[ii] = strChar[i];
	}
	return RealChar;
}
int main(int argc, char **argv)
{
	char strChar[] = "abcdef";	
	int k;
	printf("输入旋转的位数: ");
	scanf("%d",&k);

	printf("原先的字符串: ");
	for (int i=0;i<N;i++)
	{
		printf("%c",strChar[i]);
	}
	printf("\n");

	char* strCharSec;
	strCharSec = RotateLeftOne(strChar,N,k);
	printf("字符串左旋转%d位后的字符串: ",k);
	for (int j=0;j<N;j++)
	{
		printf("%c",strCharSec[j]);
	}
	printf("\n");

	return 0;
}

    第三种方法:参考了july的"程序员编程艺术"中的讲解,然后用自己的语言描述:左旋转位数k,则将字符串分为位序为:0~k-1,k~n-1,0~n-1三个部分进行先后逆序的旋转。我觉得这种方法很有趣!,而且我个人觉得事实上这里面蕴含着“分治”的思想:先将整体分割成两个小的个体,再将两个小的个体进行逆序排列,最后进行整体的归并。

    过程是这样的:比如k=2,原先字符串abcdef,则0~k-1:bacdef; 接着 k~n-1:bafedc;最后是0~n-1:cdefab。

    代码如下:

#include <stdio.h>
#include <stdlib.h>

#define N 6

//第三种方法:这一次采用分治的思想;----有趣
char* Reverse(char* SwapStr,int pos,int num)
{
	//pos:待旋转的字符串所在的首个字符位序 num:待旋转的字符串的最后一个字符位序    ---用于旋转字符串中的分治逆序旋转
	char temp;
	for (;pos<num;pos++,num--)
	{
		//这里头解决了旋转完字符串后字符位序会发生变化的问题----因为同时进行了首尾的移动
		temp = SwapStr[pos];
		SwapStr[pos] = SwapStr[num];
		SwapStr[num] = temp;
	}
	return SwapStr;
}

char* RotateLeftThr(char* strChar,int n,int k)
{
	//n:字符个数,k:左旋转位数
	k %= n;
	strChar = Reverse(strChar,0,k-1);
	strChar = Reverse(strChar,k,n-1);
	strChar = Reverse(strChar,0,n-1);
	return strChar;
}


int main(int argc, char **argv)
{
	char strChar[] = "abcdef";	
	int k;
	printf("输入旋转的位数: ");
	scanf("%d",&k);

	printf("原先的字符串: ");
	for (int i=0;i<N;i++)
	{
		printf("%c",strChar[i]);
	}
	printf("\n");

	char* strCharSec;
	strCharSec = RotateLeftThr(strChar,N,k);
	printf("字符串左旋转%d位后的字符串: ",k);
	for (int j=0;j<N;j++)
	{
		printf("%c",strCharSec[j]);
	}
	printf("\n");
	
	return 0;
}

运行结果跟第一种方法一样!



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

修罗debug

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值