二分查找、字符向中间打印

1、字符向中间打印

字符逐个逐个向中间打印


	welcome to china
	****************
	w**************a
	we************na
	wel**********ina

假设有一个字符串,再来要打印的一个字符串,从上图看出来,左边一个字符传到下面的字符串里面,右边一个字符串传到下面的字符里面;以此类推直到打印完整个字符串。

1.1数组

定义两个字符数组,存放字符;

int main()
{
	char arr1[] = {"welcome to china"};
	char arr2[] = {"****************"};
	return 0;
}

1.2下标

实现这个功能,我们可以把左边的第一个下标的元素放到下面的数组里面,右边的下标元素放下下面的数组里面;

左边的下标我们知道;那右边的下标呢?

这里我们可以用到strlen函数;假设有一个字符数组,由abcdef五个元素,对应下标是01234;那么我们可以用strlen函数计算这个数组的字符长度,字符长度是6;再减去1;就是右边的下标;

int main()
{
	char arr1[] = {"welcome to china"};
	char arr2[] = {"****************"};

	int left = 0;
	int right = strlen(arr1) - 1;

	return 0;
}

1.3代码

接下来我们就把左边和右边的元素放下去,打印字符,然后左边下标++;右边下边--;往中间缩进;那我们要打印多次,那就需要循环;

既然是往中间缩进,那么left就是小于right的,中间还有字符没有被打印;如果left等于right的话,假设字符0,是中间的字符,当left等于right,是不是也要打印字符0;那么循环t条件就是left<=right;,如果left>right;就是字符已经打印完了。

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = {"welcome to china"};
	char arr2[] = {"****************"};

	int left = 0;
	int right = strlen(arr1) - 1;

	while (left<=right)
	{
		arr2[left] = arr1[left];
		arr2[right] = arr1[right];
		printf("%s\n", arr2);
		left++;
		right--;
	}
	return 0;
}

1.4升级

那我们想观察过程可以用到Sleep休眠函数,单位是毫秒,打印一次休眠1s;

同时我们也可以再一条代码上显示中间缩进;

要用到系统指令“cls”,清屏;每打印一次,清屏;

#include<stdio.h>
#include<string.h>
#include<windows.h>
int main()
{
	char arr1[] = {"welcome to china"};
	char arr2[] = {"****************"};

	int left = 0;
	int right = strlen(arr1) - 1;

	while (left<=right)
	{
		arr2[left] = arr1[left];
		arr2[right] = arr1[right];
		printf("%s\n", arr2);
		Sleep(1000);//休眠  单位毫秒
		system("cls");
		left++;
		right--;
	}
	printf("%s\n", arr2);
	return 0;
}

2、二分查找

假设在一个有序的数组里,要找一个值的元素下标,那么通常的方法就是挨个遍历下标;

#include<stdio.h>
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int i = 0;
	int k = 7;
	scanf("%d",&k);

	int sz = sizeof(arr) / sizeof(arr[0]);
	for (i = 0; i < sz; i++)
	{
		if (arr[i] == k)
		{
			printf("%d\n",i);
			break;
		}
	}
	if (i == sz)
	{
		printf("没有找到\n");
	}
	return 0;
}

那其实这样是硬找,不管怎么样肯定能找到,但这是个有序数组啊,你无序数组也可以用这种,每次都遍历10次,就比如别人买了一双新鞋,别人说300左右,你不会从1,2,3元开始数,你会先从中间开始推,如果小了,那0~150就不用看了,那剩下的范围就是150~300之间,那我们再猜一半225,如果小了就是不用看150~255的范围,就只有255~300的范围;

2.1中间值

假设我们由10个元素,我们找k,k是7;就像问鞋那样,我们找中间值,通过中间下标找中间值,开始下标0,最后下标9;两个的中间值是4;那就是5,5比7小,那后面的01234下标的元素就不用看了,左边下标+1;为5;右边不变,再继续找中间值;5和9下标的中间值为7;下标7对应的元素是8;8比7大,那8后面的元素就不用看了;右边下标-1;左边下标不变;那5和6下标的中间值是5;下标5就是6;6比7小;左边下标+1;右边下标不变;那就是左边下标6和右边下标6的中间值是6;已经排查完所有元素,那么7的下标就是6;

2.2代码

我们需要一个数组存放数据,还有一个你输入的值,来查找它的元素下标;我们是通过中间值来判断,需要用到中间下标,那就需要左下标和右下标;右下标我们计算数组的元素个数-1;

int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
int k = 0;
scanf("%d", &k);
int left = 0;
int right = sizeof(arr1) / sizeof(arr1[0]) - 1;

我们用mid表示中间值的下标;判断中间值是小于还是大于k;小于mid+1;大于mid-1;

否则就是找到了,注意这只是写了一次,一次可能不行,还需要多次;那就需要循环;

每次减一半,每次减一半;left<right下标的;还有元素没有找到,还有一种情况是left=right下标的;找到元素;那当left>right的已经找遍了;就是都没有找到;那循环条件就是left<=right;

	while (left <= right)
	{
		int mid = (left + right) / 2;
		if (arr1[mid] < k)
		{
			left = mid + 1;
		}
		else if (arr1[mid] > k)
		{
			right = mid - 1;
		}
		else
		{
			printf("找到了,下标是%d", mid);
			break;
		}
	}

还有一种情况就是没有找到的;循环结束,跳到下面;你找到也跳到下面;但是你找到肯定是left<right;那我们进行一个判断如果left>right,那就是遍历完都没有找到;

	if (left > right)
	{
		printf("没有找到\n");
	}

3、完整代码

#include<stdio.h>
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int k = 0;
	scanf("%d", &k);
	int left = 0;
	int right = sizeof(arr1) / sizeof(arr1[0]) - 1;
	while (left <= right)
	{
		int mid = (left + right) / 2;
		if (arr1[mid] < k)
		{
			left = mid + 1;
		}
		else if (arr1[mid] > k)
		{
			right = mid - 1;
		}
		else
		{
			printf("找到了,下标是%d", mid);
			break;
		}
	}
	if (left > right)
	{
		printf("没有找到\n");
	}
	return 0;
}

或者换一种方法

#include<stdio.h>
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int k = 0;
	scanf("%d", &k);
	int left = 0;
	int right = sizeof(arr1) / sizeof(arr1[0]) - 1;
	int flag = 0;
	while (left <= right)
	{
		int mid = (left + right) / 2;
		if (arr1[mid] < k)
		{
			left = mid + 1;
		}
		else if (arr1[mid] > k)
		{
			right = mid - 1;
		}
		else
		{
			printf("找到了,下标是%d", mid);
			flag = 1;
			break;
		}
	}
	if (flag == 0)
	{
		printf("没有找到\n");
	}
	return 0;
}

感谢观看!感谢指正!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值