1、算法是想:
二分查找又称折半查找,适合对有序的数据集合进行查找,时间复杂度为O(log2n),效率高。对一升序的数据集合,先找出升序数据集合最中间的元素,将数据划分为两个子集,将最中间的元素和关键字进行比较,如果相等则返回,如果大于关键字,则在前边数据子集中查找,如果小于反之,直至找到。
2、查找步骤
(1)、首先确定查找区间的中间位置(假定是一个升序的数组),那么mid = left+(right-left)/2;
(2)、为了防止越界用待查找值与中间位置值进行比较。
<1>、若相等,则找到,输出。
<2>、若大于、则在后半区域中继续进行折半查找
<3>、若小于、则在前半区域中继续进行折半查找
(3)、查找成功,则返回关键字的数组下标。
3、图解
分析:一共尽力三次查找,第三次查找,7比中间值大,left=mid+1,使right=left,查找结束。第一次mid=4,5<7,则left=mid+1=5,继续在右侧折半查找,第二次mid=7,8>7,则right=mid-1=6,继续在左边侧折半查找。第三次mid=5,6<7,left=mid+1;left=right,找到7,下标为6。
4、代码演示:
#include
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int a = sizeof(arr) / sizeof(arr[0]);
int left = 0;
int right = a - 1; int k = 0;
scanf("%d", &k);
while (left <= right)
{
//int mid = (left + right) / 2; //这句代码放在这里,每次循环后改变mid的值
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);
break;
}
}
if (left > right)
printf("找不到\n");
return 0;
}
补充:上边红字部分
我们都知道二分查找在最坏的情况下依次是n/2,n/4,n/8....... 一直到1为止。在这种情况下,要循环多少次才能找到目标数呢,我们假设是x次。我们可以看到每次都乘以1/2,所以可以根据题意列出下面等式:
通过计算:
最后就是:
1、整体思路:
1、 通过电脑生成1~100之间的数字
2、 猜数字
3、如果你猜小了,告知你猜小了
4、 如果你猜大了,告知你猜大了
5、如果你猜大了,告知你猜大了
6、 如果你猜对了,告知你猜对了
2、实现过程:
<1>、打印菜单
输入1开始游戏,输入2退出游戏。
void menu()
{
printf("******************************\n");
printf("********** 1.play **********\n");
printf("********** 0.exit **********\n");
printf("******************************\n");
}
2、游戏逻辑
void game()//游戏逻辑:
{
int guess = 0;
//1、生成随机数
int ret = rand()%100+1 ;
//2、猜数字
while (1)
{
printf("请猜数字:>");
scanf("%d", &guess);
if (guess < ret)
{
printf("猜小了\n");
}
else if (guess > ret)
{
printf("猜大了\n");
}
else
{
printf("恭喜你,猜对了\n");
break;
}
}
}
int main()
{
srand((unsigned int)time(NULL)); //srand只需要调用一次
int input = 0;
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
printf("猜数字\n");
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,重新选择!\n");
break;
}
} while(input);
return 0;
}
注释: C语言中,生成随机数需要函数rand和srand一起使用
1、rand函数
函数原型:void rand(void),rand(void)表示rand函数没有参数
属于
头文件 rand()会返回一个范围在0~RAND_MAX(32767)之间的随机数(整数)。
2、srand函数
函数原型:void srand (usigned int seed)
属于
头文件 函数srand()用来设置函数rand()产生随机数时的随机数种子,参数seed是函数rand()种子, 用来初始rand()的起始值。
3、可以认为rand()在每次被调用的时候,它会查看:
<1>、 如果用户在此之前调用过srand(seed),给seed指定了一个值,那么它会自动调用
srand(seed)一次来初始化它的起始值。
<2>、 如果用户在此之前没有调用过srand(seed),它会自动调用srand(1)一次。
3的原文链接:https://blog.csdn.net/boatalways/article/details/27681119
根据以上:rand里面的种子没有设定,或者设定成一个定值,那么每次产生随机数是一样的。那么下面就给出时间戳的概念,在c语言中time函数可以生成c语言当前时间的时间戳。
4、time函数
函数原型:time_t time (time_t* timer);(time_t是针对时间的返回值类型,也是整型)
属于
头文件 在这里用来给srand函数做参数,给srand时刻都改变的参数。
5、用时间戳做srand的参数 srand((unsigned int)time(NULL));
在这里不想使用time的参数,给time传一个空指针(NULL);
time函数的返回类型是 time_t,srand需要的参数是unsigend int型,这里需要将time的返回类型(time_t)强转成(unsigned int)
这样就可以调用time函数给srand函数设参;time_t类型本质上是整型。
这样rand里面的种子就随着系统时间的改变而改变。
1、 判断一个数是否为奇数
#define _CRT_SECURE_NO_WARNINGS 1
#include
int main()
{
int a = 0; //给变量在内存中申请空间
scanf("%d", &a);//在这里"%d ",%d不能加空格,这样导致在输入变量a的值后,按enter键后不能跳出
//判断结果。
if (0=a%2) //0==a%2这样写更规范,防止出现漏写=,出现给a%2=0(赋值)的情况,出现0=a%2的
//情况,编译器调试不会通过,有利于及时找到错误。
{
printf("是偶数\n");
}
else
{
printf("是奇数\n");
}
return 0;
}
2、输出1-100之间的奇数,并写出其个数。
方法一:
#include
int main()
{
int i = 0;
int a = 0;
for (i = 1; i < 100; i++)
{
if (1 == i % 2)//用来判断是否为奇数
{
a++; //用来判断奇数的个数。
printf("%d ", i);//用{}将a++和printf括起来,放在一个代码块中,if就可以控制这两条
//语句,若果不加{}那么printf会将每次的结果都输出
}
//if(1 == i % 2)
// printf("%d ", i);
//a++; //如果将a++放在这里并且没加{},那么他的意义就不是计算技术的个
//数,而是计算循环次数。
}
printf("奇数的个数为%d\n", a);//这个printf放在if语句外面,不然每循环一次输出一个a,达不到
//数个数的目的
return 0;
}
方法二:
#include
int main()
{
int a = 0;
int i = 0;
while (i<100) //这里i<100而不是i<=100;是为了确保是100以内的数字,
{
a++;
if (1 == i % 2) //判断是否为奇数
printf("%d\n", i);
i=i+2;
}
printf("共输出了%d个数",a);
return 0;
}
第二种while循环方式相比第一种,循环次数减少,代码效率更高
3、计算n的阶乘
#include
int main()
{
int i = 0;
int a = 0;
int sum = 1;
scanf("%d", &a);
for (i = 1; i <= a; i++)//这里将用户输入值当作判断量
{
sum = sum * i;
}
printf("%d", sum); //放在for循环外边,是将循环最终停止sum的最终结果输出。
//若放在for循环中,每次循环sum的结果都会输出
return 0;
}
4、计算1!+2!+3!+.....+n!
方法一:
#include
int main()
{
int i = 0;
int a = 0;
int sum = 1;
int cpp = 0;
scanf("%d", &a);
for (i = 1; i <= a; i++)
{
sum = sum * i;
cpp = cpp + sum;//将cpp变量写在这里,是将每次循环sum的值进行相加,sum=sum*i计算的就是
//阶乘
}
printf("%d", cpp);
return 0;
}
方法二:
#include
int main()
{
int i = 0;
int j = 0;
int sum = 1;
int cpp = 0;
for (j = 1; j <= 3; j++) //当j++是几就求的是几的阶乘
{
sum = 1; //这里确保每次进入循环sum都是1
for (i = 1; i <= j; i++) //这个循环会算出i的阶乘
{
sum = sum * i; //每次循环sum都会被赋值,出这个for循环时sum都会保有上一次循
//环的值
}
cpp = cpp + sum;
}
printf("%d ", cpp);
return 0;
}
方法二思路: 外部for循环,如果j++等于3,外部for循环实际让循环体循环3次,
外部循环3次,那么内部for循环要循环6次,分别求1!,2!,3!
根据外部for循环的循环体可以计算出1到3的阶乘和。