查找

106 阅读1分钟

顺序查找

假设待查找元素在 i 位, 则找到需要进行 n-i+1 次比较

平均查找长度为:

i=1npi(ni+1)=1ni=1n(ni+1)=n+12\sum_{i=1}^{n}p_i(n-i+1)=\frac{1}{n}\sum_{i=1}^{n}(n-i+1)=\frac{n+1}{2}

折半(二分)查找

#include<iostream>
#include<vector>
using namespace std;

int Binary_Search(vector<int>& list, int key) {
    int low = 0, high = list.size() - 1, mid;
    while (low <= high) {
        mid = (low + high) / 2; // 取中间位置
        if (list[mid] == key) {
            return mid;
        }
        else if (list[mid] > key) {
            high = mid - 1; // 从前半部分继续查找
        }
        else {
            low = mid + 1; // 从后半部分继续查找
        }
    }
    // 查找失败, 返回 -1
    return -1;
}

int main() {
    vector<int>list = { 1,2,4,6,10,100,230,300 };
    cout << Binary_Search(list, 10);
    return 0;
}

折半查找可以等价于一颗二叉树

image.png

一个节点的查找次数 lil_i 等于其所在的高度, 而每一层有 2h12^{h-1} 个节点(h0=1)

因此平均查找长度为:

i=1npili=1ni=1hi×2i1=n+1nlog2(n+1)\sum_{i=1}^np_il_i=\frac{1}{n}\sum_{i=1}^hi×2^{i-1}=\frac{n+1}{n}log_2(n+1)

其比较次数不会超过树的高度

h=log2(n+1)h=\lceil log_2(n+1) \rceil

因此折半查找的时间复杂度为

O(logn)O(logn)

分块查找

块内可以无序, 块间有序, 索引使用折半查找, 块内使用顺序查找

image.png

#include<iostream>
#include<vector>
using namespace std;

class BlockSearch {
private:
    vector<int> index; // 索引表
    vector<int>* list; // 块

public:
    // 构造函数
    BlockSearch(vector<int>& index) :index(index) {
        list = new vector<int>[index.size()];
    }
    // 析构函数
    ~BlockSearch() { delete[] list; };

    // 插入元素
    void insert(int value) {
        // 通过索引找到对应的块
        int i = binarySearch(value);
        if (i != -1) {
            list[i].push_back(value);
        }
        else {
            cout << "插入失败\n";
        }
    }
    
    // 找到返回 true
    bool search(int data) {
        int i = binarySearch(data);

        if (i != -1) {
            // 在块内顺序查找
            for (int j = 0; j < list[i].size(); j++) {
                if (data == list[i][j]) {
                    return true;
                }
            }
        }
        return false;
    }

    // 二分查找定位索引位置
    int binarySearch(int data) {
        int low = 0, high = index.size() - 1, mid;
        while (low <= high) {
            mid = (low + high) / 2;
            if (index[mid] > data) {
                high = mid - 1;
            }
            else {
                low = mid + 1;
            }
        }
        return low;
    }
};

int main() {
    vector<int> index = { 10,20,30,40,50 };
    BlockSearch bs(index);
    bs.insert(11);
    bs.insert(13);
    bs.insert(39);
    bs.insert(12);
    bs.insert(22);
    bs.insert(21);
    bs.insert(19);
    bs.insert(35);
    bs.insert(33);

    cout << bs.search(35);
    return 0;
}