C语言——二分查找与猜数字游戏

二分查找

题目: 在一个有序数组中查找具体的某个数字n。

首先我们先定义一个1···10的数组 ,如果7为我们要查找的数字,编写代码如下

#include <stdio.h>
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	//  下标          0 1 2 3 4 5 6 7 8 9
	int k = 7;//k是要查找的数字
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
     //sz为数组元素个数
	int flag = 0;//
	for (i = 0; i < sz; i++)
	{
		if (k == arr[i])
		{
			flag = 1;
			printf("找到了,下标是:%d\n", i);
			break;
		}
	}
	if (flag == 0)
		printf("找不到\n");

	return 0;
}

但是这个代码的效率比较低,需要循环多次,所以我们需要用一个效率较高的方法:二分查找又叫 (折半查找)

二分查找的思想

给你一个有序的序列,取中间元素和目标元素进行对比,取其中的一半,丢弃另一半,快速缩小目标元素所在的位置。主要思想还是:快速缩小目标元素所在的区间。

二分查找的条件

1.序列必须是有序的,升序或者降序都可以
2. 序列必须是顺序存储元素的,顺序存储元素主要是可以快速的获取中间元素(可以通过下标来找到元素)

二分查找的实现过程

分析:假设我们要找的数字为7,在查找过程中要用下标进行查找,此时我们定义左下标为left,右下标为right,中间元素下标为mid,(left+right)/2=mid。当第一次查找没有找到时,从中间下标向左或向右缩短查找范围继续查找,直到找到为止。

  • 以数字7为例:第一次查找(left+right)/2=(0+9)/2=4,下标为4找到的数字为5,此时并没有找到;第二次查找,因为数字5小于数字7,所以mid+1=left,right不变,向右查找,此时(left+right)/2=(5+9)/2=7,下标为7,找到的数字为8,并没有找到;第三次查找,因为数字8大于数字7,所以mid-1=right,左下标不变,向左查找,此时(left+right)/2=(5+6)/2=5,下标为5,找到的数字为6,第四次查找,因为6小于7,所以向右查找,(left+right)/2=(6+6)/2=6,下标为6,找到的数字为7。
    在这里插入图片描述

代码举例

#include <stdio.h>
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	// 下标       0 1 2 3 4 5 6 7 8 9
	int k = 7;//k是要查找的数字
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	//折半查找(二分查找),前提是数组有序
	int left = 0;
	int right = sz - 1;

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

	return 0;
}

如果left是一个很大的数,right也是一个很大的数,left+right超出整形能表达的最大值,数据溢出,此时(left+right)/2所求的就不是最大值了这时要怎么办呢?
我们让多出的部分除以二在平分,如图所示
在这里插入图片描述

代码修改

#include <stdio.h>
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	//            0 1 2 3 4 5 6 7 8 9
	int k = 7;//k是要查找的数字
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	//折半查找(二分查找),前提是数组有序
	int left = 0;
	int right = sz - 1;

	int flag = 0;
	while (left<=right)
	{
		int mid = left + (right - left) / 2;

		if (arr[mid] < k)
		{
			left = mid + 1;
		}
		else if (arr[mid] > k)
		{
			right = mid - 1;
		}
		else
		{
			printf("找到了,下标是:%d\n", mid);
			flag = 1;
			break;
		}
	}
	if (flag == 0)
		printf("找不到\n");

	return 0;
}

猜数字游戏

游戏说明

1.电脑生成一个1~100的的随机数
2.猜数字
猜大了 就告诉你:猜大了
猜小了 就告诉你:猜小了
猜对了 就告诉你:恭喜你,猜对了

猜数字游戏思想

  • 首先要打印一个菜单,选择开始游戏还是退出游戏
  • 其次,游戏应该可以玩完一局之后玩一局,为循环进行,利用循环语句构建框架

代码实现

打印菜单

void menu()
{
	printf("*****************************\n");
	printf("*********   1. play  ********\n");
	printf("*********   0. exit  ********\n");
	printf("*****************************\n");
}

打印结果
在这里插入图片描述

打印主函数

int main()
{
	int input = 0;
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("猜数字\n");
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);
	return 0;
}

此时游戏过于简单,选择1要开始游戏,所以我们定义一个游戏函数game()

打印游戏函数

游戏第一步:生成随机数
rand()函数为生成随机数函数,头文件为<stdlib.h>
rand会返回一个0~327637之间的数
使用rand()要搭配srand() 一起使用,srand()是设置随机数生成器,一般用时间戳作为时间的种子,所以使用time函数来获取时间,然后将time函数转换为(unsigned)类型在传给srand函数
在这里插入图片描述
在这里插入图片描述

void game()
{
	//1. 生成随机数
	int ret = rand() % 100 + 1;//0~99+1-->1~100
	//2. 猜数字
	int guess = 0;
	while (1)
	{
		printf("请猜数字:>");
		scanf("%d", &guess);
		if (guess < ret)
		{
			printf("猜小了\n");
		}
		else if (guess > ret)
		{
			printf("猜大了\n");
		}
		else
		{
			printf("恭喜你,猜对了\n");
			break;
		}
	}
}

整体代码演示

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

void menu()
{
	printf("*****************************\n");
	printf("*********   1. play  *******\n");
	printf("*********   0. exit  ********\n");
	printf("*****************************\n");
}
//
//rand函数会返回一个0~32767之间的随机数
//
//时间戳

void game()
{
	//1. 生成随机数
	int ret = rand() % 100 + 1;//0~99+1-->1~100
	//2. 猜数字
	int guess = 0;
	while (1)
	{
		printf("请猜数字:>");
		scanf("%d", &guess);
		if (guess < ret)
		{
			printf("猜小了\n");
		}
		else if (guess > ret)
		{
			printf("猜大了\n");
		}
		else
		{
			printf("恭喜你,猜对了\n");
			break;
		}
	}
}

int main()
{
	int input = 0;
	//设置了随机数的生成器
	srand((unsigned int)time(NULL));
    //给srand传一个时间戳,是生成的数字足够随机
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);
	return 0;
}

游戏效果演示
在这里插入图片描述

  • 25
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 19
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

辭七七

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

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

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

打赏作者

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

抵扣说明:

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

余额充值