基础算法-查找:折半查找

折半查找

又称为二分查找。这种查找方法要求查找表的数据是线性结构保存,并且还要求查找表中的数据是按关键字由小到大有序排列。

折半查找(二分查找)是一种简单而又高效的查找算法,其查找长度至多为㏒2n+1(判定树的深度),平均查找长度为㏒2(n+1)-1,效率比顺序查找要高,但折半查找只能适用于顺序存储有序表(如对线性链表就无法有效地进行折半查找)。

经典非递归算法实现

int Binary_Search(int search_table[], int key, int low ,int high)
{
	while(low <= high)
	{
		mid  = (low + high) / 2;
		if(search_table[mid] < key)
		{
			low = mid + 1;
		}
		else if(search_table[mid] > key)
		{
			high = mid - 1;
		}
		else
		{
			return mid;
		}
	}//while
	
	return -1;
}

经典递归算法实现

int Binary_Search(int search_table[], int key, int low ,int high)
{
	if(low > high)
	{
		return -1;
	}
	int mid = (low + high) / 2;
	
	if(search_table[mid] == key)
	{
		return mid;
	}
	else if(search_table[mid] < key)
	{
		Binary_Search(search_table, key, mid + 1, high);
	}
	else
	{
		Binary_Search(search_table, key, low, mid - 1);
	}
}

  不过,由于折半查找的前提条件是需要有序表顺序存储,对于静态查找表,一次排序后不再变化,这样的算法已经比较好了。但是对于频繁执行插入或删除操作的数据集来说,维护有序的排序会带来不小的工作量,那就不建议使用了。

说一个小的知识点:

mid = (first + last) / 2;
//等价于
mid = first + (last - first) / 2;

如果把一个有序的线性数组放到一个二维数组中,那么同样可以利用二分查找:

在这个数组上面查找

bool searchMatrix(vector<vector<int>>& matrix, int target) 
{
	bool found = false;
	int m = matrix.size();//行数
	int n = matrix[0].size();//列数
	
	int first = 0;
	int last = m * n - 1;
	
	while(first <= last)
	{
		int mid = (first + last) / 2;
		
		if(matrix[mid / n][mid % n] == target)
		{
			found = true;
			break;
		}
		else if(matrix[mid / n][mid % n] > target)
		{
			last = mid - 1;
		}
		else
		{
			first = mid + 1;
		}
		
	}//while
	
	return found;
}  

折半查找扩展

 折半查找的思想其实就是,每次查找之后,能缩小下次查找的范围,这一点很重要。以后所有的查找问题,只要是在有序的线性表上查找或者半有序的线性表上查找,都要往折半查找上靠拢,想着每次查找之后,能缩小下次查找的范围。

在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。
请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

  只要遇到了有序的查找,就往折半查找上想办法,同时想着怎么能缩小下次查找的范围。

bool searchMatrix(vector<vector<int>>& matrix, int target) 
{
	int row = matrix.size();
	int column = matrix[0].size();
	
	bool found = false;
	
	int i = 0;
	int j = column - 1;
	while(i < row && j >= 0)
	{
		if(matrix[i][j] > target)
		{
			--j;
		}
		else if(matrix[i][j] < target)
		{
			++i;
		}
		else
		{
			found = true;
			break;
		}
	}//while
	
	return found;
}

  这里存储二维数组用的是vector,当然也可以用一个int类型的指针,然后通过行数和列数访问二维数组每一个元素。

原文地址:https://www.cnblogs.com/stemon/p/4475792.html