栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

从有序数组中查找数字的4种方法/二分查找/二分查找的函数递归/一一对比/一一对比的递归

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

从有序数组中查找数字的4种方法/二分查找/二分查找的函数递归/一一对比/一一对比的递归

目录

情境设置:

第一种方案:一一对比

函数递归:

函数递归有两个必要条件:

第二种方案一一对比的进阶版--函数递归

图解:

第三种方案:二分查找

二分查找主要的流程

 

第四种方案二分查找进阶方案--函数递归

图解:

总结:


 

 

情境设置:

从一组有序数组中1,2,3,4,5,6,7,8,9,10中找数字。

第一种方案:一一对比

Step1,将有序的数字放到数组中

Step2,设置循环,一个一个的与要找的数进行比较。

int main()
{
	int arr[] = {1,2,3,4,5,6,7,8,9,10};//将有序的数字放到数组中。
	int i = 0;//要查找的数字
	int n = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);//求数组中元素个数
	scanf("%d", &i);
	for (n = 0; n < sz; n++)
	{
		if (arr[n] == i)
		{
			printf("找到了,下标为%d", n);
			break;
		}
	}
	if (n > 9)
		printf("找不到");
	return 0;
}

 

函数递归:

什么时候可以用函数递归呢?

在我看来,重复执行某一些相同或者类似的”动作“,可以考虑函数递归。

函数递归的中心思想就是大事化小,个人理解就是将我们重复执行的一些相同的或者类似的“动作”,作为一个动作,反复执行。(有点像循环,但不一样)

函数递归有两个必要条件:

1.每一次递归之后,我们都要离递归结束的条件(限制条件)越来越近。

2.需要有一个限制条件,使我们的递归结束

第二种方案一一对比的进阶版--函数递归

我们来分析下:

重复动作:一个一个比较,我们一直在重复这个动作

限制条件的设置:我们什么时候会不比较了呢?要么是找到了,要么是没找到的时候。

我们来看代码

#include 
int search(int* pa,int k,int sz)//  pa是指针指向首元素(arr[0])的地址 
{
	//比较的是  当前进入函数pa所指向的地址,与arr[10]的地址的地址比较  
	//pa+sz 每一次递归进来都是arr[10]的地址
	if ( pa <= (pa+sz) )  //限制条件:每一次递归进来,判断有没有越界
	{
		if (*pa != k)     //判断当前地址所指向的元素是不是与要找的k相同
			return 1 + search(pa + 1, k,sz-1);
		//pa+1-->每递归一次,pa指向后面一个元素的地址  
		//sz-1-->保证了每次递归之后 pa+sz 指向的都是arr[10]的地址
		else
			return 0;
	}
	else  
		return 0;
//只要每没有找到,返回0
}
int main()
{
	 int arr[] = { 1,2,3,4,5,6,7,8,9,10 };//13
	 int sz = sizeof(arr) / sizeof(arr[0]) - 1;
	 // sz-->数组的最大下标-->先求的是数组元素个数,再减一。
	 int k = 0;
     scanf("%d", &k);
	 int ret = search(arr,k,sz);
	 //参数分别为 数组首元素的地址 要找的数 数组的最大下标
	 if (ret > 9)
		 printf("找不到");
	 else
		 printf("找到了,下标为%d", ret);
	return 0;
}
图解:

①②...表示每一次递推的顺序

紫色的1,2,3,4...是返回的值

这里是k > 10 的情况

红色线代表递推出去,紫色线代表回归。

 

 

 为什么ret接收的是10呢?(可以打开监视测试一下),我们search函数进去了11次, ,回去的时候也是11次。回去的时候呢,有10次是return 1+search() , 1次是 结束函数递归的时候,return 0 ; 

所谓递归,一去一回。从哪里进来的,回哪里去,每一次回归,都是回到 return 1+ search(pa+1,k,sz-1)的地方

第三种方案:二分查找

一一对法,太过繁琐,每一次都需要比较很多的值才能确定有没有我们要找的数字。

我想大家应该有玩过猜数字的游戏吧。1-100之间的数字,让你去猜,你为了缩小范围先猜50,在看看大了还是小了,在缩小一半,以此类推。

这就是我们的二分查找。

二分查找主要的流程

知左(右)下标,求中间下标,在比较。比较一次,没找到,看k(要找的数)是在中间数的左边还是右边,调整左下标或者右下标,再求中间下标,再比较。一直重复这个动作。直到有一次,我们左下标大于右下标,结束。

int mid_search(int arr[],int sz,int k)
{
	int left = 0;//最左边的下标
	int right = sz - 1;//最右边的下标
	while (left <= right)//循环的限制条件  
    //在每一次找不到的时候,left或者right会发生改变,直到不满足条件为止,跳出循环
	{
		int mid = left + (right - left) / 2;//找出中间元素的下标
		if (arr[mid] > k)//用中间元素与我们要比较的值判断
			//中间值大,则说明k可能在中间值的右边
			right = mid - 1;//调整我们的最右边的下标
		else if (arr[mid] < k)
			//中间值小,则说明k可能在中间值的左边
			left = mid + 1;//调整我们最左边的下标
		else
			return mid;//找到了就会返回中间元素的下标
	}
	//如果没找到,我们的 left 将会大于 right 跳出循环
	return 10;//没找到的时候,返回值与if(ret>9)相呼应
}
int main()
{
	int arr[] = {1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);//求出数组中元素的个数
	int k = 0;
	scanf("%d", &k);
	int ret = mid_search(arr,sz,k);
	//函数参数分别为 数组首元素地址,元素个数,要找的数
	if (ret>9)
		printf("找不到");
	else
		printf("找到了,下标为%d",ret);
	return 0;
}
 

简单图解 :

第四种方案二分查找进阶方案--函数递归
int mid_search(int left, int right,int* pa,int  k)
{
	int mid = left + (right - left) / 2; //找中间的数的下标  
	if (left <= right)
	{
		if (*(pa + mid ) < k) 
		{
			left = mid + 1;
			return mid_search(left, right, pa, k);
		}
		else if (*(pa + mid ) > k)  
		{
			right = mid - 1;
			return mid_search(left, right, pa, k);
		}
		else
			return mid;
	}
    ruturn 10;  //根据我们主函数中的判断的条件设置
}
int main()
{
	 int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	 int k = 0;
	 int left = 0;
	 int right = sizeof(arr) / sizeof(arr[0]) - 1;
     scanf("%d", &k);
	 int ret = mid_search(left,right,arr,k);
	 //参数为左下标,右下标,首元素地址,要查找的数
	 if (ret>=10)
		 printf("找不到");
	 else
		 printf("找到了,下标为%d", ret);
	return 0;
}
图解:

解释:红色线是递推,橙色线是回归。 

总结:

我们讲了从有序数组中查找数字的4种方法。

一一对比和进阶版,二分查找和进阶版

让我们更深入了解函数递归。

函数递归,既有递推,又有回归。回归的时候,从哪里来回哪里去。

 

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1030791.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号