Binary Search 的递归与迭代实现及STL中的搜索相关内容

与排序算法不同,搜索算法是比较统一的,常用的搜索除hash外仅有两种,包括不需要排序的线性搜索和需要排序的binary search。

首先介绍一下binary search,其原理很直接,不断地选取有序数组的组中值,比较组中值与目标的大小,继续搜索目标所在的一半,直到找到目标,递归算法可以很直观的表现这个描述:

int binarySearchRecursive(int A[], int low, int high, int key)
{
    if (low > high) return -1;
    int mid = (low + high) >> 1;
    if (key < A[mid]) return binarySearchRecursive(A, low, mid - 1, key);
    else if (key > A[mid]) return binarySearchRecursive(A, mid + 1, high, key);
    else return mid;
}

但实际上,递归方法的时间效率和空间效率都不如迭代方法,迭代方法才是常用的binary search,代码如下:

int binarySearch(int A[], int low, int high, int key)
{
    int mid;
    while (low <= high)
    {
        mid = (low + high) >> 1;
        if (key < A[mid]) high = mid - 1;
        else if (key > A[mid]) low = mid + 1;
        else return mid;
    }
    return -1;
}

简单计算一下Binary Search的效率:

算法流程:

1.检查上下边界--2.获取中值--3.比较--左半边进入子问题/右半边进入自问题/获得结果

1,2所需时间为常数时间,设为C。3阶段以一半的数据量重新运行函数,所以:

T(n)=T(n/2)+C

设n=2^k,则有T(2^k)=T(2^(k-1))+C=(T(2^(k-2))+C)+C=T(1)+k*C

即T(n)=log(n)*C+T(1),所以binary search是一个O(log(n))的算法。

测试函数:

void searchTest()
{
    int a[] = { 1,2,3,4,5,7,9,11,17,20,23,39 };
    cout << binarySearch(a, 0, 11, 39) << endl;
    cout << binarySearch(a, 0, 11, 37) << endl;
    cout << binarySearch(a, 5, 10, 39) << endl;
    cout << endl;
    cout << binarySearchRecursive(a, 0, 11, 39) << endl;
    cout << binarySearchRecursive(a, 0, 11, 37) << endl;
    cout << binarySearchRecursive(a, 5, 10, 39) << endl;
}

测试结果如下:

11
-1
-1

11
-1
-1
请按任意键继续. . .

传统C函数中有bsearch这一函数,因为在现代C++中使用C库运行效率很低,加上接口并不好用,不再提及。而STL中,有以下几个关于搜索的函数。他们均作用于各个STL容器。

int count(起始迭代器,终止迭代器,key value)

return key value的数量

iterator find(起始迭代器,终止迭代器,key value)

成功:return 找到的第一个key value的迭代器

失败:return 终止迭代器

bool binary_search(起始迭代器,终止迭代器,key value)

return 是否找到

iterator lower_bound(起始迭代器,终止迭代器,key value)

return 大于或等于key value的第一个迭代器,若所有值都小于key value,返回终止迭代器

iterator upper_bound(起始迭代器,终止迭代器,key value)

return 大于key value的第一个迭代器,若所有值都小于key value,返回终止迭代器

这些函数中,count和find是作用于任意排序对象的,其效率为O(n),而binary_search, lower_bound, upper_bound是作用于有序对象的,其效率是O(logN)。

下面代码给出这些STL函数的测试:

void searchTest()
{
    vector<int> b{ 1,2,3,4,4,7,9,11,17,20,23,39 };
    cout << "vector<int> b{ 1,2,3,4,4,7,9,11,17,20,23,39 };" << endl;
    cout << "count(b.begin(), b.end(), 4):"
        << count(b.begin(), b.end(), 4) << endl;
    cout << endl;
    cout << "find(b.begin(), b.end(), 39) - b.begin():"
        << find(b.begin(), b.end(), 39) - b.begin() << endl;
    cout << "find(b.begin(), b.end(), 4) - b.begin():"
        << find(b.begin(), b.end(), 4) - b.begin() << endl;
    cout << "find(b.begin(), b.end(), 37) - b.begin():"
        << find(b.begin(), b.end(), 37) - b.begin() << endl;
    cout << "find(b.begin() + 5, b.begin() + 10, 39) - b.begin():"
        << find(b.begin() + 5, b.begin() + 10, 39) - b.begin() << endl;
    cout << endl;
    cout << "binary_search(b.begin(), b.end(), 39):"
        << binary_search(b.begin(), b.end(), 39) << endl;
    cout << "binary_search(b.begin(), b.end(), 37):"
        << binary_search(b.begin(), b.end(), 37) << endl;
    cout << endl;
    cout << "lower_bound(b.begin(), b.end(), 39) - b.begin():"
        << lower_bound(b.begin(), b.end(), 39) - b.begin() << endl;
    cout << "lower_bound(b.begin(), b.end(), 4) - b.begin():"
        << lower_bound(b.begin(), b.end(), 4) - b.begin() << endl;
    cout << "lower_bound(b.begin(), b.end(), 37) - b.begin():"
        << lower_bound(b.begin(), b.end(), 37) - b.begin() << endl;
    cout << "lower_bound(b.begin() + 5, b.begin() + 10, 39) - b.begin():"
        << lower_bound(b.begin() + 5, b.begin() + 10, 39) - b.begin() << endl;
    cout << endl;
    cout << "upper_bound(b.begin(), b.end(), 39) - b.begin():"
        << upper_bound(b.begin(), b.end(), 39) - b.begin() << endl;
    cout << "upper_bound(b.begin(), b.end(), 4) - b.begin():"
        << upper_bound(b.begin(), b.end(), 4) - b.begin() << endl;
    cout << "upper_bound(b.begin(), b.end(), 37) - b.begin():"
        << upper_bound(b.begin(), b.end(), 37) - b.begin() << endl;
    cout << "upper_bound(b.begin() + 5, b.begin() + 10, 39) - b.begin():"
        << upper_bound(b.begin() + 5, b.begin() + 10, 39) - b.begin() << endl;
}

测试结果:

vector<int> b{ 1,2,3,4,4,7,9,11,17,20,23,39 };
count(b.begin(), b.end(), 4):2

find(b.begin(), b.end(), 39) - b.begin():11
find(b.begin(), b.end(), 4) - b.begin():3
find(b.begin(), b.end(), 37) - b.begin():12
find(b.begin() + 5, b.begin() + 10, 39) - b.begin():10

binary_search(b.begin(), b.end(), 39):1
binary_search(b.begin(), b.end(), 37):0

lower_bound(b.begin(), b.end(), 39) - b.begin():11
lower_bound(b.begin(), b.end(), 4) - b.begin():3
lower_bound(b.begin(), b.end(), 37) - b.begin():11
lower_bound(b.begin() + 5, b.begin() + 10, 39) - b.begin():10

upper_bound(b.begin(), b.end(), 39) - b.begin():12
upper_bound(b.begin(), b.end(), 4) - b.begin():5
upper_bound(b.begin(), b.end(), 37) - b.begin():11
upper_bound(b.begin() + 5, b.begin() + 10, 39) - b.begin():10
请按任意键继续. . .

时间: 2024-12-19 18:32:47

Binary Search 的递归与迭代实现及STL中的搜索相关内容的相关文章

泛型的Binary Search Tree的实现,并与STL map进行操作性能上的比较

问题描述: 1.binary search tree是一种排序二叉树.对于key值,当前节点的小于左孩子的大于右孩子的: 2.binary search tree不是自平衡树.所以,当插入数据不是很随机时候,性能会接近O(N),N是树中节点数目; 3.理想状态下,时间复杂度是O(lgN), N是树中节点的数目: 4.下面给出一个简单的实现,并比较其和STL map的性能,一样的操作,大约耗时为STL map 的2/3: 代码如下: #ifndef _BINARY_SEARCH_TREE_H_ #

二叉树的遍历,递归,迭代,层序,中序,前序,后序

#include<stdio.h> #include<stdlib.h> #include<queue> #include<stack> #include<iostream> using namespace std; struct node{ int key; node *left, *right; }; void insertTree(node* &root,int val) { node* tmp = (node*)malloc(si

[LeetCode] Unique Binary Search Trees II (难以忍受的递归)

Given n, generate all structurally unique BST's (binary search trees) that store values 1...n. For example, Given n = 3, your program should return all 5 unique BST's shown below. 1 3 3 2 1 \ / / / \ 3 2 1 1 3 2 / / \ 2 1 2 3 class Solution { private

[C++]LeetCode: 93 Binary Search Tree Iterator (经典题,非递归的中序遍历)

题目: Implement an iterator over a binary search tree (BST). Your iterator will be initialized with the root node of a BST. Calling next() will return the next smallest number in the BST. Note: next() and hasNext() should run in average O(1) time and u

[C++]LeetCode: 53 Unique Binary Search Trees

题目: Given n, how many structurally unique BST's (binary search trees) that store values 1...n? For example, Given n = 3, there are a total of 5 unique BST's. 1 3 3 2 1 \ / / / \ 3 2 1 1 3 2 / / \ 2 1 2 3 背景知识: 二叉查找树(英语:Binary Search Tree),也称二叉搜索树.有序二

Cracking the Coding Interview, Binary Tree, Binary Search Tress

Binary Tree: 0到2个子节点; Binary Search Tree: 所有左边的子节点 < node自身 < 所有右边的子节点: 1. Full类型: 除最下面一层外, 每一层都有两个子节点: 2. Complete类型: 除最下面一层外为Full类型, 但是最下面一层最所有子节点靠左: 3. Balanced类型: 左右两个子树的长度相差小于等于一: traverse: 遍历: recursion: 递归(反复用自身): iteration: 迭代(循环): 3种遍历: 1.

二分搜索(Binary Search)

当我们在字典中查找某个单的时候,一般我们会翻到一个大致的位置(假设吧,翻到中间位置),开始查找.如果翻到的正好有我们要的词,那运气好,查找结束.如果我们要找的词还在这个位置的前面,那我们对前面的这一半词典继续搜索,翻到某个位置(假设是四分之一的位置)等等.这个二分搜索的工作原理一样.相应的算法就叫做二进制搜索算法. 迭代版本算法: //iterative binary search which returns index of element int binarySearchIterative(

[LeetCode] 701. Insert into a Binary Search Tree

Given the root node of a binary search tree (BST) and a value to be inserted into the tree, insert the value into the BST. Return the root node of the BST after the insertion. It is guaranteed that the new value does not exist in the original BST. No

leetcode--98. Validate Binary Search Tree

1.问题描述 Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is defined as follows: The left subtree of a node contains only nodes with keys less than the node's key. The right subtree of a node contains only nodes wi