Lesson 6 二分查找和函数

二分查找

用于有序数组的数据快速查找。注意无序数组无法用二分查找。

基本思想

类似昨天实现的猜数字游戏中人类的思考过程。猜数字的范围在1~100之间,那么首先猜50,然后按照被猜测值与猜测值之间的大小关系再确定下一个猜测数字。如果被猜测数字比50大,那么猜75,如果小,猜25。如此反复直到猜中。可以看到,每次猜测都可以去掉当前范围内一半的数字,这种方法对于有序的数组查找非常有用。

实现

假设有一个数组:

int arr[10] = {1,2,3,4,5,6,7,8,9,10};

需要输入一个数字n,然后在数组中查找这个数字。如果数组中有和输入数字一样的值,返回这个值的下标,否则就返回未找到。
这里会涉及3个变量:leftrightmid。开始的时候,left为数组第一个元素的下标,right为最后一个元素的下标,mid为中间元素的下标(如果数组是偶数,居中的两个中的任何一个都可以)。首先使用arr[mid]与数字n做比较。如果n>arr[mid],说明数字在 arr[mid]右边, 那么此时left = mid+1(相当于数字范围的下限被加大了)。如果n<arr[mid],说明数字在 arr[mid]左边, 那么此时right = mid-1(相当于数字范围的上限被缩小了)。然后新的mid = left+(right-left)/2。这样继续下去,直到n == arr[mid]或者一直没有找到。
看一下代码:

int binary_search(int arr[], int sz, int n)
{
	int left = 0;
	int right = sz - 1;
	while (left <= right)
	{
		int mid = left + (right - left) / 2;
		if (n > arr[mid])
		{
			left = mid + 1;
		}
		else if (n < arr[mid])
		{
			right = mid - 1;
		}
		else
			return mid+1;
	}
	return 0;

}

int main()
{
	int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int n = 0;

	while (scanf("%d", &n) != EOF)
	{
		int ret = binary_search(arr, sz, n);
		if (ret)
		{
			printf("找到了,下标是%d\n", ret-1);
		}
		else
		{
			printf("没找到\n");
		}
	}
	return 0;
}

写这段代码的时候,碰到一个小bug。如果输入数字1,会打印没找到。实际上1对应的是arr[0]。之前写的binary_search返回值是mid,如果mid == 0,对于下面的判断就会出问题了。所以修改为返回mid+1,打印为ret-1

函数

叫函数不便理解,其英文是function,意思就是功能 。所以函数就是实现某个功能的代码。

函数的基本语法

return_type function_name(para_type para1,para_type para2, para_type para3...)
{
	function body;
}

形象一些的:

int Add(int x,int y)
{
	int sum = 0;
	sum = x+y;
	return sum;
}

一个函数需要有返回类型、函数名、函数体。一个函数可以没有参数,可以没有返回值(对应返回类型为void)。

库函数和自定义函数

库函数在printf和scanf里有详细介绍,这里不再赘述。主要说说自定义函数。自定义函数是用户自己定义的,实现某个功能的函数。例如上面的代码中,Add就是一个自定义函数。这个函数的返回类型是int,函数名是Add,参数是xy。关于自定义函数,需要注意:

  1. 返回值与返回类型必须匹配;
  2. 参数类型与实际传进来的参数必须匹配,否则会有隐式类型转换;
  3. 没有返回值的函数的返回类型是void

形参与实参

形参是实参的一份复制,形参仅在函数被调用的时候在内存中开辟空间,否则就是一段代码。函数被调用时,改变形参的值不会改变实参的值。举个例子:

void test(int x,int y)
{
	x = 0;
	y = 0;
}

int main()
{
	int a = 10;
	int b = 20;
	test(a,b);
}

这里执行了test函数之后实际不改变a和b的值。

return的功能

return是函数的返回值,执行到return之后函数跳出,不再执行return之后的语句。如果函数中有分支语句,需要保证任何情况下都有返回,否则报错。

函数的嵌套和链式访问

函数嵌套是说在一个函数内部调用其他函数。链式访问是指一个函数的返回值作为另一个函数的参数被传入。

函数嵌套

先看一段代码:

void test();
{
	printf("%d\n",100);
}

int main()
{
	test();
	return 0;
}

这个是在test函数内部嵌套了printf函数。

链式访问

看一下代码:

printf("%d",printf("%d",printf("%d",43)));

这段代码会在屏幕上打印:4321。这是因为,printf的返回值是其在屏幕上打印字符的个数。最里层的printf打印了43,然后返回值2作为中间层的printf参数,打印了2之后,中间层函数的返回值又会作为最外层的参数,最后打印就是4321

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值