一、二分查找法
1.用Python3编写:
def binary_search(list, item):
# low 和 high 用于跟踪要在其中查找的部分
low = 0
high = len(list) - 1
# 只要范围没有缩小到只有一个元素,就继续循环
while low <= high:
# 检查中间的元素
mid = (low + high) // 2 # 这里注意下,必须是 // 而不是 /,否则会报错
guess = list[mid]
# 如果猜的数是对了,返回结果
if guess == item:
return mid
# 如果猜的数大了,上限减1
if guess > item:
high = mid - 1
# 如果猜的数小了,下限加1
else:
low = mid + 1
# 如果没有这个元素,返回None
return None
my_list = [1, 3, 5, 7, 9] ##测试数据
运行结果为:
2.用C语言编写:
#include <stdio.h>//二分查找算法即测试用例
int BinySerch(int *arr, int x, int lengh)//设计参数,由于是整形数组,所以我们必须传递他
{ //长度否则数组传参时会发生降级
int left = 0, right = lengh - 1;
int mid ;
while (left <= right)
{
mid = left + (right - left) / 2;
if (x < arr[mid])
{
right = mid - 1;
}
else if (x > arr[mid])
{
left = mid + 1;
}
else
{
return mid;
}
}
return -1;
}
int main()//测试用例
{
int x = 0;
int arr[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int lengh = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < 12; i++)
{
printf("%d ",BinySerch(arr, i, lengh));
}
return 0;
}
3.二分查找的优缺点:
虽然二分查找的效率高,其花费时间为O(lgn)但是要将表按关键字排序。而排序本身是一种很费时的运算。既使采用高效率的排序方法也要花费O(nlgn)的时间。
二分查找只适用顺序存储结构。为保持表的有序性,在顺序结构里插入和删除都必须移动大量的结点。因此,二分查找特别适用于那种一经建立就很少改动、而又经常需要查找的线性表。
对那些查找少而又经常需要改动的线性表,可采用链表作存储结构,进行顺序查找。链表上无法实现二分查找。
二、大O表示法
大O表示法是一种特殊的表示法,指出了算法的速度有多快。
常见的大O运行时间:
- O(log n) ,也叫对数时间,这样表示的算法包括二分查找。
- O(n) ,也叫线性时间,这样的算法包括简单查找。
- O(n * log n) ,这样的算法包括快速排序。
- O(), 这样的算法包括选择排序。
- O( n! ),这样的算法包括旅行商的解决方案。
关于大O运行时间的小结:
- 二分查找的速度比简单查找要快许多,数据越大,差距就越明显。
- O(log n)比O(n)快。需要搜索的元素越多,前者比后者就快得越多。
- 算法运行时间并不以秒为单位。
- 算法运行时间是从其增速的角度来度量的。
- 算法运行时间用大O表示法表示。
三、课后练习和习题答案
1、练习 (P8)
1.1 假设有一个包含128个名字的有序列表,你要使用二分查找法在其中查找一个 名字,请问最多需要几步才能找到?
128->64->32->16->8->4->2->1,所以最多需要7步。
1.2上面列表的长度翻倍之后,最多需要几步?
翻倍后顶多会增加一步,所以是8步。
1、练习 (P13)
使用大O表示法给出下属各种情况的运行时间
1.3 在电话簿中根据名字查找电话号码。
根据字母姓式二分查找所用时间为:O(log n)
1.4 在电话簿中根据电话号码找人。(提示:你必须查找整个电话簿。)
简单查找,所用时间为:O(n)
1.5 阅读电话簿中每个人的电话号码
简单查找,所用时间为:O(n)
1.6阅读电话簿中姓名以A打头的人的电话号码。
简单查找,所用时间为:O(n)