C语言数组中字符串的旋转(左旋与右旋)
在数组中定义一个字符串,该字符串由“ abcdef ” 组成,所谓左旋即是让左边的第一个字符旋转到右边去,左旋一个字符即是产生“ bcdefa ”这样的字符串,右旋与之相反。
为了控制左(右)旋的字符数,需要制作一个可以改变旋转字符数的函数。
字符串的旋转的主要si思想是将需要寻转的字符先进行存储,然后将剩余的不需要旋转的字符移位,将需要旋转的字符的位置取代,为旋转的字符留下足够的空间来存储旋转字符。所以先建立一个数组,将旋转字符存储在内,然后将原数组内的元素移位后面的元素取代其前面的元素,但万不可将 " \0 " 移动或取代,要始终保证 " \0 " 在其原来的位置,然后将所存储的元素再次赋值到原数组中,完成旋转。最后再将数组元素循环打印在屏幕上。
一.字符串的左旋(右旋)
由于左旋和右旋思路一致,这里仅介绍左旋方法。
这种题目有两种思路:
1.首字符的后置以及其余元素的往前推置,循环重复此过程K次(k为左旋字符个数)。
eg:
字符串为“ABCDEF\0”,要旋转2个字符,
首先保存首字符到一个变量,然后把其余变量全部提前一位置放,即为“BCDEF \0”(此处注意,最后的终止符\0不要提前,留出一个空位)
再把用来保存的变量给字符串最后一个位置(除\0外),即为“BCDEFA\0”
再做一次此过程即为“CDEFGA \0”——》“CDEFGAB\0”
源代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void Exchange(char *str, int k)
{
int i,m;
char temp;
char *sta;
for (i = 0; i < k; i++)
{
sta = str;
temp = *str;//保存首字符
for (m = 0; m <= (int)strlen(str)-1; m++)//元素提前放置
{
*sta = *(sta + 1);
sta++;
}
*(str+strlen(str)) = temp;//将首字符放置最后
}
}
int main()
{
int leng;
printf("请输入要左旋几个字符\n");
scanf("%d", &leng);
char str[] = "ABCDEFG";
Exchange(str,leng);
printf("%s\n", str);
return 0;
}
2.三步旋转法
这种方法是由观察得来,旋转后的字符串有此规律:
旋转前“ABCDEFG”
旋转后“CDEFGAB”
将旋转后的字符逆置得
“CDEFGBA”
将未旋转的字符逆置得
“GFEDCBA”
再将全部字符逆置就得到了原来的字符串“ABCDEFG”
原字符串旋转时反向操作即可
源代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void reverse(char *left, char *right)//逆置函数
{
char temp;
while (left < right)
{
temp = *left;
*left = *right;
*right = temp;
left++; right--;
}
}
void Exchange(char *str, int leng)//三步逆置
{
reverse(str, str + leng-1);
reverse(str + leng, str+strlen(str)-1);
reverse(str, str + strlen(str) - 1);
}
int main()
{
int leng;
printf("请输入要左旋几个字符\n");
scanf("%d", &leng);
char str[] = "ABCDEFG";
Exchange(str,leng);
printf("%s\n", str);
system("pause");
return 0;
}
二.判断一个字符串是否是由另一个字符串旋转而来
1.第一种思路是不借助字符串库函数,将需要判断的字符串按照三步逆置法判断是否和原字符串相同,但是这种方法效率较差,而且时间复杂度高。
源代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void reverse(char *left,char *right)
{
char temp;
while (left < right)
{
temp = *left;
*left = *right;
*right = temp;
left++; right--;
}
}
int judgeStr(char str1[],char str2[],char str3[])
{
int i,m=0,sum=0,s;
char *sta ;
char *fina ;
int length = strlen(str1);
for (i = 0; i <(int)strlen(str2); i++)
{
str3[i] = str2[i];
}
for (i = 0; i <= (int)strlen(str1) - 1; i++)
{
sta = str3;
fina = str3 + strlen(str1) - 1;
reverse(sta, sta + i);
reverse(sta + i + 1, fina);
reverse(sta, fina);
for (; m < (int)strlen(str1); m++)
{
if (str1[m] != str3[m])
{
sum++;
break;
}
}
for (s = 0; s<(int)strlen(str2); s++)
{
str3[s] = str2[s];
}
if (sum == 4)
{
return 0;
}
}
return 1;
}
int main(void)
{
char str1[] = "ABCDE";
char str2[] = "BCDEA";
char str3[] = "BACDE";
char stra[] = "AAAAA";
int judge;
judge = judgeStr(str1, str2,stra);
if (judge == 1)
{
printf("str2是由str1旋转得来的\n");
}
else
{
printf("str2不是由str1旋转得来的\n");
}
judge = judgeStr(str1, str3,stra);
if (judge == 1)
{
printf("str3是由str1旋转得来的\n");
}
else
{
printf("str3不是由str1旋转得来的\n");
}
system("pause");
return 0;
}
2.使用字符串库函数解决
使用此方法需要注意到一个规律:
一个字符串后面再接一个和自身相同的字符串后,此字符串中就出现了所有旋转可以得到的结果。
eg:
A B C D A B C D,其中有所有的“ABCD”旋转结果,BCDA(2~5),CDAB(3~6),DABC(4~7)。
所以做法就是利用库函数将原字符串拼接一个自身,再在字符串中查找需要判断的字符串即可。
源代码:
#include<stdio.h>
#include<string.h>
int judge(char *str1, char *str2)
{
strncat(str1, str1, strlen(str1));//原字符串拼接本身
char *result = strstr(str3, str2);//查找目标字符串
if (result == NULL)
{
return -1;
}
else
{
return 0;
}
}
int main()
{
char str1[] = "ABCDE";
char str2[] = "CDEAB";
char str3[] = "DEBAC";
int result = judge(str1, str2);
if (result == -1)
{
printf("str2不是由str1旋转得到\n");
}
else
{
printf("str2是由str1旋转得到\n");
}
result = judge(str1, str3);
if (result == -1)
{
printf("str3不是由str1旋转得到\n");
}
else
{
printf("str3是由str1旋转得到\n");
}
system("pause");
return 0;
}