二分查找概念:
二分查找算法是在有序数组中用到的较为频繁的一种算法,二分查找其实是分治算法的一个实例;
针对有序表的查找方法,比较次数少,查找快,平均性能好。插入删除比较困难。一般用于有序的不常插入删除而查找频繁的表;
步骤:
1、获取表的中间键,将中间键与查找的键相比;
2、如果查找键小于中间键,则去中间键左半部分查,否则去中间键右半部分查找;
3、重复1,2步骤;
时间复杂度分析:
假设该数组的长度是N那么二分后是N/2,再二分后是N/4……直到二分到1结束,那么二分的次数就是比较的次数,于是我们可以设次数为x,N*(1/2)^x=1,按时间复杂度取最重要的增长量级即为lgN;
c#代码实现:
public int search() { int key = 2; int[] a = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; int low = 0; int high = a.Length - 1;Stack st = new Stack(); while (low <= high) { int mid = low + (high - low) / 2; if (a[mid] > key) { high = mid - 1; } else if (a[mid] < key) { low = mid + 1; } else { return mid; } } return -1; }
erlang代码实现(列表实现):
%% erlang实现的列表二分查找,erlang:length,erlang:nth等函数都可以用遍历实现,这里为了方便直接采用 binary_search(Key, List) -> High = erlang:length(List), Low = 1, do_binary_search(Low, High, Key, List). do_binary_search(Low, High, _Key, _List) when Low > High -> %% 查找不到,返回-1 -1; do_binary_search(Low, High, Key, List) -> Mid = Low + (High - Low) div 2, %% 求出中间键 Value = lists:nth(Mid, List), %% 获取中间键的值,尾递归遍历获取,性能消耗 if Key > Value -> %% 大于中间键的值,去后半部分查找 do_binary_search(Mid + 1, High, Key, List); Key < Value -> %% 小于中间键的值,去前半部分查找 do_binary_search(Low, Mid - 1, Key, List); true -> %% 直接返回查找的键 Mid end. %%注意:传入的List是列表 ,因为lists:nth的遍历有较大的性能消耗;
erlang代码实现(tuple实现):
binary_search_tuple(Key, List) -> Tuple = erlang:list_to_tuple(List), High = erlang:tuple_size(Tuple), Low = 1, do_binary_search_tuple(Low, High, Key, Tuple). do_binary_search_tuple(Low, High, _Key, _Tuple) when Low > High -> -1; do_binary_search_tuple(Low, High, Key, Tuple) -> Mid = Low + (High - Low) div 2, Value = erlang:element(Mid, Tuple), if Key > Value -> do_binary_search_tuple(Mid + 1, High, Key, Tuple); Key < Value -> do_binary_search_tuple(Low, Mid - 1, Key, Tuple); true -> Mid end.
erlang(尾递归顺序查找、列表实现二分查找、元组实现二分查找)timer:tc测试:
1、10w条有序整数列表,查找key = 10w的多次测试平均时间:
(1)尾递归顺序查找:3177
(2)list实现的erlang二分查找:74770
(3)tuple实现的erlang二分查找:1090
2、100w条有序整数列表,查找key = 100w的多次测试平均时间:
(1)尾递归顺序查找:23929
(2)list实现的erlang二分查找:696093
(3)tuple实现的erlang二分查找:11835
3、上面测试结果可以看出当达到一定数量级时,tuple实现的方式效率会比较高。list方式实现因为list:nth是采用遍历的方式获取元素,会消耗性能。