交换与逆置,冒泡排序,字符串逆置,字符串左旋

交换操作

逆置程序在C语言的学习中是非常常见的,而所谓逆置,就是把后面的元素和前面的进行交换。
显而易见,所有的逆置都离不开交换,最基础的就是交换三连,不常用的就是用算数运算符 ‘^’ 将元素进行交换,还有用加减操作进行交换。
交换三连

int main()
{
	int a = 1, b = 2;
	int tmp = a;
	a = b;
	b = tmp;
	return 0;
}
//这样借助一个临时空间tmp就可以交换a和b了

异或交换

int main()
{
	int a = 1, b = 2;
	a = a^b;
	b = a^b;
	a = a^b;
	return 0;
}

用加减实现交换

int main()
{
	int a = 1, b = 2;
	a = a + b ;
	b = a - b;
	a = a - b;
	printf("%d %d", a,b);
	system("pause");
	return 0;
}

这些就是基础的排序交换操作了,加减操作和异或操作的原理类似,都是利用计算机的二进制计算原理进行的,相较于交换三连,优点是不创建临时变量。 我们平时学习和写代码时,大多数只需要用到交还三连即可。
今天我们来整理一下在C语言学习过程中见过的逆置程序。

一、冒泡排序

前面我们写过的冒泡排序就是最基础的啦,还记得吗?
来看一下思想:

  对一个数组内的所有元素进行排序,
  设置两个索引i和j分别控制  比较的趟数  和  每一趟的比较  
  如果符合条件,就交换这两个数,一个循环嵌套下来,排序就完成啦

具体的代码就不再呈现了,详细的可以看看之前的文章:冒泡排序

倒置字符串

牛客网链接:逆置字符串
题目:

将一句话的单词进行倒置,标点不倒置。
比如 I like beijing. 经过函数后变为:beijing. like I

思路(以题例为例):

  我们首先来思考一下 I like beijing.怎样变成  beijing. like I 呢?
  我们可以 先将整个字符串都逆置 得到:.gnijieb ekil I 
  我们发现空格的位置没有改变
  可以再进行操作,把每个单词都进行逆置就可以的到beijing. like I啦

代码:

思路出来了,怎么写代码呢?
显然,我们需要进行很多次逆置,一个一个写未免太繁琐,我们可以先写一个逆置函数
用逆置函数可以直接将整个字符串进行逆置
逆置单词时,我们只需要确定好单词的起始位置,就可以用逆置函数进行交换了。
我们写来看看。
// 字符串逆置函数
// 交换三连有些变化,是因为当它变成函数时,传入的字符串数组退化为指针,只能用指针解引用来实现对实参的操作
void reverse(char* input,int len)
{
	char* left = input;
	char* right = input + len - 1;
	while (left<right)
	{
		char tmp = *left;
		*left = *right;
		*right = tmp;
		left++;
		right--;
	}
}

// 精准逆置
void WordReverse(char* input)
{
	// 先针对整个字符串进行逆序
	reverse(input, strlen(input));
	//进行每个单词的逆置
	//要用到start对字符串进行遍历
	char* start = input;
	while (start != '\0')
	{
		//用end对作为每个单词的末尾
		//知道每个单词的开始和末尾就可以对单词进行逆置了
		char*end = start;
		while (*end != ' '&&*end != '\0')
		{
			end++;
		}
		//这个循环完成之后,end指向了该单词末尾。此时就可以进行逆置啦!
		reverse(start, end-start);           //这里start就是input
		//这个单词逆置完之后,就要进行下一个单词的逆置了
		//此时有两种情况:
		//                  ① end==‘\0’(break跳出)
		//                  ② end==‘ ’ (让start=end+1继续循环,处理下一个单词)
		if (*end == '\0')
		{
			break;
		}
		else
		{
			start = end + 1;
		}
		//循环完成时,所有的逆置工作就完成了。
	}
}

int main()
{
	while (1)
	{
		//进行后续操作
		char input[101] = { 0 };
		//读取数据
		//这里不能用scanf(),因为scanf遇到空格就结束了。
		//可以用ges()读取这一行的内容,注意用法: 返回char*类型,遇到NULL结束
		char*ret = gets(input);
		if (ret == NULL)    //数据读取结束
		{
			break;
		}
		//逆置
		WordReverse(input);
		//打印
		printf("%s\n",input);
	}
	return 0;
}

字符串左旋

题目:
实现一个函数,可以左旋字符串中的k个字符。
例如:
ABCD左旋一个字符得到BCDA
ABCD左旋两个字符得到CDAB
思路:

 这个题的思路很多,
 最简单的就是:设置循环,将第一个元素存进一个临时变量里,后面所有元素的进行平移,但这样做未免太麻烦。
 改进:我们可以用库函数对字串进行拼接,把后面的先用strcpy()拷贝出来,再用strncat()接上,最后再拷回去,只需要注意拼接的起始位置就好了
 
 那我们能不能这样:
 例如:ABCDEFG,左旋3次后变成DEFGABC
 先将要左旋的前三个逆序(CBADEFG),然后将后半段逆序(CBAGFED)
 最后整体逆序(DEFGABC),这样是不是只需要用一个交换函数就可以完成这个左旋功能啦!
 我们写来看看。
//先来一个交换三连
void Reverse(char*arr, char*start, char*end)
{
	while (start<end)
	{
		char tmp = *start;
		*start = *end;
		*end = tmp;
		start++;
		end--;
	}
}
//然后对字符串进行操作
void StrReverse(char*arr, int time)    //我们需要规定交换的次数
{
	int len = strlen(arr);
	int pos = time%len;               //如果字长为5,那么旋转6次,旋转11次和旋转1次是一样的,那么我们用交换次数模上一个长度,就可以求k,也就是pos
	Reverse(arr, 0, pos - 1);         //逆置前半段
	Reverse(arr, pos, len - 1);       //逆置后半段
	Reverse(arr, 0, len - 1);         //逆置整个字符串
}
void main()
{
	int time;
	char str[] = "ABCDEF";
	printf("请输入操作数");
	scanf("%d", &time);
	StrReverse(str, time);
	printf("%s\n", str);
}

总结

逆置循环交换,在具体的题目中,我们大可以设置一个交换逆置函数,函数的参数标明交换内容的首端和末端,这样我们就可以用这一个逆置函数去解决更复杂的逆置。
这是一种思想,解决问题时,很复杂的问题很可能是同一个小问题实现很多次得到的。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值