字符串左旋右旋——三步旋转法和移相法

题目:实现一个函数,可以左旋字符串中的k个字符。
AABCD左旋一个字符得到ABCDA
AABCD左旋两个字符得到BCDAA

方法一:三步旋转法

左旋程序思路:首先根据画图得知左旋后的结果,然后在分析实现的简约步骤;
第一步:字符串全逆序;
第二步:左边的字符串逆序;
第三步:右边的字符串逆序;

举例:左旋K=1个字符:

首先是头文件和主函数部分:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<windows.h>
#include<assert.h>
#include<string.h>


int main()
{
	char arr[] = "aabcd";/*未定义的数组内容不能用{}括起来,只能采用“”的形式。*/
	printf("%s\n", my_left_move(arr, 1));/*表示左旋一个字符*/
	system("pause");
	return 0;
}

接下来是左旋函数实现部分:

char* my_left_move(  char *src, int count)/* 函数的实现,此处的src是指针变量,不能加coonst常属性,是不可修改的左值*/
{
	int i = 0;
	int len = strlen(src);
	char tmp = 0;
	assert(src);//断言指针的有效性
	for (i = 0; i < len/2; i++)//第一步:整体逆序
	{
		采用了数组的方式:并且循环条件除以2是为了优化算法;
		/*tmp = src[i];
		src[i] = src[i + len-1];
		src[i + len-1] = tmp;*/
		采用指针的形式符合函数定义
	     tmp=*(src+i);
		 *(src + i) = *(src  + len - 1-i);//此处的下标要自己去分析的src变成了src+len-1,+i变成了-i;
		 *(src + len - 1 - i) = tmp;
	}
	for (i = 0; i <(len-count)/2 ; i++)//第二步:左边的字符串逆序
	{
		tmp = *(src + i);
		*(src + i) = *(src + len -count- 1 - i);
		*(src + len - count-1 - i) = tmp;
	}
	for (i=0; i <count/2; i++)//第三步:右边的字符串逆序
	{
		tmp =*(src + len -count+i) ;
		*(src + len -count  + i) = *(src+len-1-i);
		*(src + len - 1 - i) = tmp;
	}
	return src;
}


然后是整个程序:(左旋一个字符)

左旋一个字符:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<windows.h>
#include<assert.h>
#include<string.h>

char* my_left_move(  char *src, int count)/* 函数的实现,此处的src是指针变量,不能加coonst常属性,是不可修改的左值*/
{
	int i = 0;
	int len = strlen(src);
	char tmp = 0;
	assert(src);//断言指针的有效性
	for (i = 0; i < len/2; i++)//第一步:整体逆序
	{
		采用了数组的方式:并且循环条件除以2是为了优化算法;
		/*tmp = src[i];
		src[i] = src[i + len-1];
		src[i + len-1] = tmp;*/
		采用指针的形式符合函数定义
	     tmp=*(src+i);
		 *(src + i) = *(src  + len - 1-i);//此处的下标要自己去分析的src变成了src+len-1,+i变成了-i;
		 *(src + len - 1 - i) = tmp;
	}
	for (i = 0; i <(len-count)/2 ; i++)//第二步:左边的字符串逆序
	{
		tmp = *(src + i);
		*(src + i) = *(src + len -count- 1 - i);
		*(src + len - count-1 - i) = tmp;
	}
	for (i=0; i <count/2; i++)//第三步:右边的字符串逆序
	{
		tmp =*(src + len -count+i) ;
		*(src + len -count  + i) = *(src+len-1-i);
		*(src + len - 1 - i) = tmp;
	}
	return src;
}
int main()
{
	char arr[] = "aabcd";/*未定义的数组内容不能用{}括起来,只能采用“”的形式。*/
	printf("%s\n", my_left_move(arr, 1));/*表示左旋一个字符*/
	system("pause");
	return 0;
}


举例:左旋K=2个字符:

无论左旋多少个字符,方法一样,只是在区分左串和右串的时候把要移动的字符串看做一个整体,其内部顺序不变;

同样的先是头文件和主函数:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<windows.h>
#include<assert.h>
#include<string.h>

int main()
{
	char arr[] = "aabcd";/*未定义的数组内容不能用{}括起来,只能采用“”的形式。*/
	printf("%s\n", my_left_move(arr, 2));/*表示左旋两个字符*/
	system("pause");
	return 0;
}


接下来是左旋函数实现部分:

char* my_left_move(char *src, int count)/* 函数的实现,此处的src是指针变量,不能加coonst常属性,是不可修改的左值*/
{
	int i = 0;
	int len = strlen(src);
	char tmp = 0;
	assert(src);//断言指针的有效性
	for (i = 0; i < len / 2; i++)//第一步:整体逆序
	{
		采用了数组的方式:并且循环条件除以2是为了优化算法;
		/*tmp = src[i];
		src[i] = src[i + len-1];
		src[i + len-1] = tmp;*/
		采用指针的形式符合函数定义
		tmp = *(src + i);
		*(src + i) = *(src + len - 1 - i);//此处的下标要自己去分析的src变成了src+len-1,+i变成了-i;
		*(src + len - 1 - i) = tmp;
	}
	for (i = 0; i <(len - count) / 2; i++)//第二步:左边的字符串逆序
	{
		tmp = *(src + i);
		*(src + i) = *(src + len - count - 1 - i);
		*(src + len - count - 1- i) = tmp;
	}
	for (i = 0; i <count / 2; i++)//第三步:右边的字符串逆序
	{
		tmp = *(src + len - count + i);
		*(src + len - count + i) = *(src + len - 2 - i);
		*(src + len - 2- i) = tmp;
	}
	return src;
}



然后是整个程序:(左旋两个字符)

 

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<windows.h>
#include<assert.h>
#include<string.h>
char* my_left_move(char *src, int count)/* 函数的实现,此处的src是指针变量,不能加coonst常属性,是不可修改的左值*/
{
	int i = 0;
	int len = strlen(src);
	char tmp = 0;
	assert(src);//断言指针的有效性
	for (i = 0; i < len / 2; i++)//第一步:整体逆序
	{
		采用了数组的方式:并且循环条件除以2是为了优化算法;
		/*tmp = src[i];
		src[i] = src[i + len-1];
		src[i + len-1] = tmp;*/
		采用指针的形式符合函数定义
		tmp = *(src + i);
		*(src + i) = *(src + len - 1 - i);//此处的下标要自己去分析的src变成了src+len-1,+i变成了-i;
		*(src + len - 1 - i) = tmp;
	}
	for (i = 0; i <(len - count) / 2; i++)//第二步:左边的字符串逆序
	{
		tmp = *(src + i);
		*(src + i) = *(src + len - count - 1 - i);
		*(src + len - count - 1- i) = tmp;
	}
	for (i = 0; i <count / 2; i++)//第三步:右边的字符串逆序
	{
		tmp = *(src + len - count + i);
		*(src + len - count + i) = *(src + len - 2 - i);
		*(src + len - 2- i) = tmp;
	}
	return src;
}
int main()
{
	char arr[] = "aabcd";/*未定义的数组内容不能用{}括起来,只能采用“”的形式。*/
	printf("%s\n", my_left_move(arr, 2));/*表示左旋两个字符*/
	system("pause");
	return 0;
}

方法二:移相法

我们可以通过画图的方式来实现移相左旋:

我们直接来做左旋K=2个字符的:

01.<span style="font-size:18px;color:#ff0000;"><strong>  
02.</strong></span>#define _CRT_SECURE_NO_WARNINGS 1  
03. #include<assert.h>  
04. #include<windows.h>  
05. #include<stdio.h>  
06. #include<string.h>  
07. void  my_left_move(char* str, int count)  
08. {  
09.  assert(str);  
10.  int i = 0;  
11.  int len = strlen(str);  
12.  if (len <= 1)  
13.  {  
14.   return ;  
15.  }  
16.  for (i = 0; i <count; i++)  
17.  {  
18.   int j = 0;  
19.   char  tmp = str[0];  <span style="font-size:18px;color:#ff0000;"><strong>//把第一个字符保存起来</strong></span>  
20.  for (j = 0; j < len - 1; j++)  
21.   {  
22.      
23.    *(str + j) = *(str + j + 1);  <span style="font-size:18px;"><span style="color:#ff0000;"><strong>//然后依次进行平移</strong>  
24.</span></span>  }  
25.   *(str + len - 1) = tmp;  <span style="color:#ff0000;"><strong><span style="font-size:18px;">//再把tmp保存的内容赋给最后一个空位</span></strong>  
26.</span> }  
27. }  
28.int main()  
29. {  
30.  char arr[] = "AABCD";  
31.  int k= 2;  
32.  my_left_move(arr, k);  
33.  printf("%s\n", arr);  
34.  system("pause");  
35.  return 0;  
36. }    



总结:左旋一个字符或者多个字符的唯一差别就是在最后一步右边字符串的逆序个数上,循环条件K即count变了呢!

那么做完左旋的你是不是也想做一做右旋呢?其实你只要画画图就知道,右旋和左旋其实是一样的只不过你在区分左串和右串的起始位置有所不同而已!

那么这里给出一个右旋K=count字符的右旋实现程序:(采用三步旋转法)

(传参合适的K)

这里也可以采用移相法!!!

<strong>char* my_right_move(char *src, int count)/* 函数的实现,此处的src是指针变量,不能加coonst常属性,是不可修改的左值*/
{
	int i = 0;
	int len = strlen(src);
	char tmp = 0;
	assert(src);//断言指针的有效性
	for (i = 0; i < len / 2; i++)//第一步:整体逆序
	{
		采用了数组的方式:并且循环条件除以2是为了优化算法;
		/*tmp = src[i];
		src[i] = src[i + len-1];
		src[i + len-1] = tmp;*/
		采用指针的形式符合函数定义
		tmp = *(src + i);
		*(src + i) = *(src + len - 1 - i);//此处的下标要自己去分析的src变成了src+len-1,+i变成了-i;
		*(src + len - 1 - i) = tmp;
	}
	for (i = 0; i <(len - count) / 2; i++)//第二步:左边的字符串逆序
	{
		tmp = *(src + i);
		*(src + i) = *(src + len - count - 1 - i);
		*(src + len - count - 1 - i) = tmp;
	}
	for (i = 0; i <count / 2; i++)//第三步:右边的字符串逆序
	{
		tmp = *(src + len - count + i);
		*(src + len - count + i) = *(src + len - 1 - i);
		*(src + len - 1 - i) = tmp;
	}
	return src;
}</strong>

题目:判断一个字符串是否为另外一个字符串旋转之后的字符串。
例如:给定s1 = AABCD和s2 = BCDAA,返回1,给定s1 = abcd和s2 = ACBD,返回0.


AABCD左旋一个字符得到ABCDA
AABCD左旋两个字符得到BCDAA

AABCD右旋一个字符得到DAABC
AABCD右旋两个字符得到CDAAB

同样先把头文件和主函数编好:

16.#define _CRT_SECURE_NO_WARNINGS 1  
17.#include<assert.h>  
18.#include<windows.h>  
19.#include<stdio.h>  
20.#include<string.h>  
21.  
22.int main()  
23.{  
24.    char arr[] = "AABCD";  
25.    int ret = my_move(arr, "ABCDA");  
26.    if (ret == 1)  
27.    {  
28.        printf("yes\n");  
29.    }  
30.    else  
31.    {  
32.        printf("no\n");  
33.    }  
34.    system("pause");  
35.    return 0;  
36.}  
37.  

然后是函数实现部分:

char my_move(char* str1, char* str2)  
42.{  
43.    assert(str1);  
44.    assert(str2);  
45.    int len = strlen(str1);  
46.    strncat(str1, str1, len);  
47.    if (strstr(str1, str2))  
48.    {  
49.        return 1;  
50.    }  
51.    else  
52.    {  
53.        return 0;  
54.    }  
55.}  

最后是整个程序:

01.#define _CRT_SECURE_NO_WARNINGS 1  
02.#include<assert.h>  
03.#include<windows.h>  
04.#include<stdio.h>  
05.#include<string.h>  
06.char my_move(char* str1, char* str2)  
07.{  
08.    assert(str1);  
09.    assert(str2);  
10.    int len = strlen(str1);  
11.    strncat(str1, str1, len);  
12.    if (strstr(str1, str2))  
13.    {  
14.        return 1;  
15.    }  
16.    else  
17.    {  
18.        return 0;  
19.    }  
20.}  
21.int main()  
22.{  
23.    char arr[] = "AABCD";  
24.    int ret = my_move(arr, "ABCDA");  
25.    if (ret == 1)  
26.    {  
27.        printf("yes\n");  
28.    }  
29.    else  
30.    {  
31.        printf("no\n");  
32.    }  
33.    system("pause");  
34.    return 0;  
35.}  


 
      .
<span style="color:#cc0000;">  </span>

哈哈,到这里,整个左旋右旋相信已经一目了然了,继续加油吧!


 


 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值