目录
二、折半查找(二分查询)
二分查询也称折半查找(Binary Search)它是一种效率较高的查找办法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。
1.查询过程分析
首先,线性表中元素是按升序排列,将线性表中间位置的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录线性表分成left、right两个子线性表,如果中间位置记录的关键字大于查找关键字,则查找right子表,否则查找left子表。重复以上过程,直到找到满足条件的关键字,使查找成功,返回位置信息,或子表中不存在关键字也就子表空了,此时查找不成功,返回-1。
2.非递归的代码实现
int binarySearch(int* nums, int n, int key)
{
int left = 0, right = n - 1;
int mid = 0;
int pos = -1;
while (left <= right)
{
mid = (right + left) / 2;
if (nums[mid] > key)
{
right = mid - 1;
}
else if (nums[mid] < key)
{
left = mid + 1;
}
else
{
pos = mid;
break;
}
}
return pos;
}
3.递归代码实现
int BinaryFind(int* nums, int left, int right, int key)
{
int pos = -1;
if (left <= right)
{
int mid = (left + right) / 2;
if (nums[mid] > key)
{
pos=BinaryFind(nums, left, mid - 1, key);
}
else if (nums[mid] < key)
{
pos=BinaryFind(nums, mid + 1, right, key);
}
else
{
pos = mid;
}
}
return pos;
}
4.算法复杂度分析
二分查找的基本思想是将n个元素分成大致相等的两部分,取nums[n/2]与key做比较:
如果key == nums[n/2],则找到|key,算法中止;
如果key <nums[n/2],则只要在数组nums的左半部分继续搜索key;
如果key >nums[n/2],则只要在数组nums的右半部搜索key;
时间复杂度即是while循环的次数。
总共有n个元素,
渐渐跟下去就是n, n/2, n/4,. n/2Nk(接下来操作元素的剩余个数),其中k就是循环的次数
由于你n/2个k取整后>=1
即令n/2Ak = 1
可得k= log2 n,(是以2为底,n的对数)
所以时间复杂度可以表示O(h)=O(log2n)。
5.顺序表关键字递增有序,但有重复关键字
5.1查询最左端的val
int binarySearch(int* nums, int n, int key)
{
int left = 0, right = n - 1;
int mid = 0;
int pos = -1;
while (left <= right)
{
mid = (right + left) / 2;
if (nums[mid] > key)
{
right = mid - 1;
}
else if (nums[mid] < key)
{
left = mid + 1;
}
else
{
if (mid == left || nums[mid - 1] != key)
{
pos = mid;
break;
}
right = mid - 1;
}
}
return pos;
}
5.2查询最右端的val
int binarySearch(int* nums, int n, int key)
{
int left = 0, right = n - 1;
int mid = 0;
int pos = -1;
while (left <= right)
{
mid = (right + left) / 2;
if (nums[mid] > key)
{
right = mid - 1;
}
else if (nums[mid] < key)
{
left = mid + 1;
}
else
{
if (mid == right || nums[mid + 1] != key)
{
pos = mid;
break;
}
left = mid + 1;
}
}
return pos;
}