数据结构查找算法(二分查找)

二分查找

二分查找算法,说白了就是在有序的数组里面给予一个存在数组里面的值key,然后将其先和数组中间的比较,如果key大于中间值,进行下一次mid后面的比较,直到找到相等的,就可以得到它的位置。

  • 前提: 线性表中的记录必须是关键字有序(通常从小到大),线性表必须采用顺序存储。
  • 基本思想: 取中间记录作为比较对象,若给定值与中间记录的关键字相等,则查找成功;若给定值小于中间记录的关键字,则在中间记录的左半区继续查找;否则,在右半区查找。不断重复,直到查找成功或查找失败为止。
  • 复杂度\boldsymbol{O(log(n))}

二分算法步骤描述

前提:有序数组中查找关键词所在的位置

  1. 首先确定整个查找区间的中间位置 mid = strat+(end-strat)/2

  2. 用待查关键字key值与中间位置的关键字值进行比较;

    若相等,则查找成功

    若key小于a[k],则在前(左)半个区域继续进行折半查找\boldsymbol{arr[low,mid-1]}

    若key大于a[k],则在后(右)半个区域继续进行折半查找\boldsymbol{arr[mid+1,high]}

  3. 对确定的缩小区域再按折半公式,重复上述步骤。

二分查找的应用场景:

二分查找目的是在一堆数中找到指定的数。

使用二分查找这些数据需要有的特征(面试容易问):

  1. 存储在数组中。
  2. 有序的排列。

如果是链表就无法使用二分查找。

顺序数组是递增递减,是否有重复的数据没有关系。

二分查找的实现(递归算+非递归)

递归算

折半查找,递归实现(模板)

/*折半查找,递归实现*/  
template<class T>  
int Binary_Search(T *x, int N, T keyword)  
{  
    int low = 0, high = N-1,mid;  
    while(low <= high)  
    {  
        mid = (low + high)/2;  
        if(x[mid] == keyword)  
            return mid;  
        if(x[mid] < keyword)  
            low = mid + 1;  
         else  
            high = mid -1;  

    }  
    return -1;  
}  

折半查找,递归实现

/*折半查找,递归实现*/  
int binarySearch(int *arr , int low , int high , int target)//递归实现
{
	int middle = (low + high)/2;
	if(low > high)
		return -1;
	if(arr[middle] == target)
		return middle;
	if(arr[middle] > target)
		return binarySearch( arr , low , middle - 1 , target);
	if(arr[middle] < target)
		return binarySearch( arr , middle + 1 , high , target);
 
};

非递归实现

 /**
     * 二分查找普通实现。
     * @param srcArray 有序数组
     * @param key 查找元素
     * @return  不存在返回-1,存在返回对应的数组下标
     */
    
int binarySearch1(int a[], int n , int target)//循环实现
{
    int low = 0 ,high = n , middle;
    middle = (low + high)/2;
    if (key == a[middle]) {
        return mid;
    }
    
	while(low < high)
	{
	   middle = (low + high)/2;
       if(target == a[middle])
		   return middle;
	   else if(target > a[middle])
		   low = middle +1;
	   else if(target < a[middle])
		   high = middle;
	}
	return -1;
};

参考例子

#include<iostream>
using namespace std;
int binarySearch(int *arr , int low , int high , int target)//递归实现
{
	int middle = (low + high)/2;
	if(low > high)
		return -1;
	if(arr[middle] == target)
		return middle;
	if(arr[middle] > target)
		return binarySearch( arr , low , middle - 1 , target);
	if(arr[middle] < target)
		return binarySearch( arr , middle + 1 , high , target);
 
};
 
int binarySearch1(int a[], int n , int target)//循环实现
{
	int low = 0 ,high = n , middle;
	while(low < high)
	{
	   middle = (low + high)/2;
       if(target == a[middle])
		   return middle;
	   else if(target > a[middle])
		   low = middle +1;
	   else if(target < a[middle])
		   high = middle;
	}
	return -1;
};
 
int main()
{
	int a[10] = {5,6,7,8,9, 10 , 11, 12 ,13, 14};
	int index = binarySearch( a , 0 , 9 , 12);
	cout<<index<< endl;
	int index2 = binarySearch1(a,10,12);
	cout<<index2<< endl;
	system("pause");
}

后记:

查找和排序都是在程序设计中经常用到的算法,查找相对而言较为简单,不外乎顺序查找、二分查找、哈希表查找和二叉排序树查找。
在面试的时候,不管是用循环还是用递归,面试官都期待应聘者能够信手拈来写出完整的二分查找代码,否则可能连继续面试的兴趣都没有。
以上两句话引出自《剑指Offer:名企面试官精讲典型面试题》

1.算法是程序的灵魂,优秀的程序在对海量数据处理时,依然保持高速计算,就需要高效的数据结构算法支撑。2.网上数据结构算法的课程不少,但存在两个问题:1)授课方式单一,大多是照着代码念一遍,数据结构算法本身就比较难理解,对基础好的学员来说,还好一点,对基础不好的学生来说,基本上就是听天书了2)说是讲数据结构算法,但大多是挂羊头卖狗肉,算法讲的很少。 本课程针对上述问题,有针对性的进行了升级 3)授课方式采用图解+算法游戏的方式,让课程生动有趣好理解 4)系统全面的讲解了数据结构算法, 除常用数据结构算法外,还包括程序员常用10大算法二分查找算法(非递归)、分治算法、动态规划算法、KMP算法、贪心算法、普里姆算法、克鲁斯卡尔算法、迪杰斯特拉算法、弗洛伊德算法、马踏棋盘算法。可以解决面试遇到的最短路径、最小生成树、最小连通图、动态规划等问题及衍生出的面试题,让你秒杀其他面试小伙伴3.如果你不想永远都是代码工人,就需要花时间来研究下数据结构算法。教程内容:本教程是使用Java来讲解数据结构算法,考虑到数据结构算法较难,授课采用图解加算法游戏的方式。内容包括: 稀疏数组、单向队列、环形队列、单向链表、双向链表、环形链表、约瑟夫问题、栈、前缀、中缀、后缀表达式、中缀表达式转换为后缀表达式、递归与回溯、迷宫问题、八皇后问题、算法的时间复杂度、冒泡排序、选择排序、插入排序、快速排序、归并排序、希尔排序、基数排序(桶排序)、堆排序、排序速度分析、二分查找、插值查找、斐波那契查找、散列、哈希表、二叉树、二叉树与数组转换、二叉排序树(BST)、AVL树、线索二叉树、赫夫曼树、赫夫曼编码、多路查找树(B树B+树和B*树)、图、图的DFS算法和BFS、程序员常用10大算法二分查找算法(非递归)、分治算法、动态规划算法、KMP算法、贪心算法、普里姆算法、克鲁斯卡尔算法、迪杰斯特拉算法、弗洛伊德算法马踏棋盘算法。学习目标:通过学习,学员能掌握主流数据结构算法的实现机制,开阔编程思路,提高优化程序的能力。
做一门精致,全面详细的 java数据结构算法!!! 让天下没有难学的数据结构, 让天下没有难学的算法, 不吹不黑,我们的讲师及其敬业,可以看到课程视频,课件,代码的录制撰写,都是在深夜,如此用心,其心可鉴,他不掉头发,谁掉头发??? 总之你知道的,不知道的,我们都讲,并且持续更新,走过路过,不要错过,不敢说是史上最全的课程,怕违反广告法,总而言之,言而总之,这门课你值得拥有,好吃不贵,对于你知识的渴求,我们管够管饱 话不多说,牛不多吹,我们要讲的本门课程内容: 稀疏数组、单向队列、环形队列、单向链表、双向链表、环形链表、约瑟夫问题、栈、前缀、中缀、后缀表达式、中缀表达式转换为后缀表达式、递归与回溯、迷宫问题、八皇后问题、算法的时间复杂度、冒泡排序、选择排序、插入排序、快速排序、归并排序、希尔排序、基数排序(桶排序)、堆排序、排序速度分析、二分查找、插值查找、斐波那契查找、散列、哈希表、二叉树、二叉树与数组转换、二叉排序树(BST)、AVL树、线索二叉树、赫夫曼树、赫夫曼编码、多路查找树(B树B+树和B*树)、图、图的DFS算法和BFS、程序员常用10大算法二分查找算法(非递归)、分治算法、动态规划算法、KMP算法、贪心算法、普里姆算法、克鲁斯卡尔算法、迪杰斯特拉算法、弗洛伊德算法马踏棋盘算法
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页