以下是8种经典查找算法的完整C++实现,包括详细注释、时间/空间复杂度分析和测试代码。
完整实现代码
/**
* 8种经典查找算法完整C++实现
* 编译: g++ -std=c++11 -O2 search_algorithms.cpp -o search
*/
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <queue>
#include <map>
#include <unordered_map>
#include <memory>
#include <iomanip>
using namespace std;
// ==================== 工具函数 ====================
template<typename T>
void printArray(const vector<T>& arr, const string& name = "") {
if (!name.empty()) cout << name << ": ";
for (const auto& val : arr) cout << val << " ";
cout << endl;
}
// 生成有序数组用于查找
vector<int> generateSortedArray(int n) {
vector<int> arr(n);
for (int i = 0; i < n; i++) {
arr[i] = i * 2; // 偶数序列,确保间隔
}
return arr;
}
// ==================== 1. 顺序查找 ====================
/**
* 时间复杂度: O(n)
* 空间复杂度: O(1)
* 适用: 无序数组/链表
*/
template<typename T>
int sequentialSearch(const vector<T>& arr, const T& target) {
for (size_t i = 0; i < arr.size(); i++) {
if (arr[i] == target) {
return static_cast<int>(i);
}
}
return -1; // 未找到
}
// 带哨兵的顺序查找(减少比较次数)
template<typename T>
int sequentialSearchWithSentinel(vector<T>& arr, const T& target) {
if (arr.empty()) return -1;
// 将目标值放入末尾作为哨兵
T last = arr.back();
arr.back() = target;
size_t i = 0;
while (arr[i] != target) {
i++;
}
// 恢复原数组
arr.back() = last;
if (i < arr.size() - 1 || arr.back() == target) {
return static_cast<int>(i);
}
return -1;
}
// ==================== 2. 二分查找 ====================
/**
* 时间复杂度: O(log n)
* 空间复杂度: O(1) 迭代, O(log n) 递归
* 适用: 有序数组
*/
// 迭代版本
template<typename T>
int binarySearchIterative(const vector<T>& arr, const T& target) {
int left = 0;
int right = static_cast<int>(arr.size()) - 1;
while (left <= right) {
int mid = left + (right - left) / 2; // 避免溢出
if (arr[mid] == target) {
return mid;
} else if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1;
}
// 递归版本
template<typename T>
int binarySearchRecursiveHelper(const vector<T>& arr, const T& target,
int left, int right) {
if (left > right) return -1;
int mid = left + (right - left) / 2;
if (arr[mid] == target) {
return mid;
} else if (arr[mid] < target) {
return binarySearchRecursiveHelper(arr, target, mid + 1, right);
} else {
return binarySearchRecursiveHelper(arr, target, left, mid - 1);
}
}
template<typename T>
int binarySearchRecursive(const vector<T>& arr, const T& target) {
return binarySearchRecursiveHelper(arr, target, 0, static_cast<int>(arr.size()) - 1);
}
// 查找第一个等于target的位置
template<typename T>
int binarySearchFirst(const vector<T>& arr, const T& target) {
int left = 0;
int right = static_cast<int>(arr.size()) - 1;
int result = -1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] == target) {
result = mid;
right = mid - 1; // 继续在左半部分查找
} else if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return result;
}
// 查找最后一个等于target的位置
template<typename T>
int binarySearchLast(const vector<T>& arr, const T& target) {
int left = 0;
int right = static_cast<int>(arr.size()) - 1;
int result = -1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] == target) {
result = mid;
left = mid + 1; // 继续在右半部分查找
} else if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return result;
}
// 查找第一个大于等于target的位置
template<typename T>
int binarySearchLowerBound(const vector<T>& arr, const T& target) {
int left = 0;
int right = static_cast<int>(arr.size()) - 1;
int result = static_cast<int>(arr.size()); // 如果没有找到,返回末尾
while (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] >= target) {
result = mid;
right = mid - 1;
} else {
left = mid + 1;
}
}
return result;
}
// 查找第一个大于target的位置
template<typename T>
int binarySearchUpperBound(const vector<T>& arr, const T& target) {
int left = 0;
int right = static_cast<int>(arr.size()) - 1;
int result = static_cast<int>(arr.size()); // 如果没有找到,返回末尾
while (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] > target) {
result = mid;
right = mid - 1;
} else {
left = mid + 1;
}
}
return result;
}
// ==================== 3. 插值查找 ====================
/**
* 时间复杂度: O(log log n) 平均, O(n) 最坏
* 空间复杂度: O(1)
* 适用: 均匀分布的有序数组
*/
template<typename T>
int interpolationSearch(const vector<T>& arr, const T& target) {
int left = 0;
int right = static_cast<int>(arr.size()) - 1;
// 确保目标值在数组范围内
if (target < arr[left] || target > arr[right]) {
return -1;
}
while (left <= right && target >= arr[left] && target <= arr[right]) {
if (left == right) {
return (arr[left] == target) ? left : -1;
}
// 计算插值位置
int pos = left + static_cast<int>((static_cast<double>(right - left) /
(arr[right] - arr[left])) * (target - arr[left]));
// 防止越界
pos = max(left, min(pos, right));
if (arr[pos] == target) {
return pos;
} else if (arr[pos] < target) {
left = pos + 1;
} else {
right = pos - 1;
}
}
return -1;
}
// ==================== 4. 斐波那契查找 ====================
/**
* 时间复杂度: O(log n)
* 空间复杂度: O(1)
* 适用: 有序数组,避免除法运算
*/
vector<int> generateFibonacci(int n) {
vector<int> fib;
if (n <= 0) return fib;
fib.push_back(0);
if (n == 1) return fib;
fib.push_back(1);
for (int i = 2; i < n; i++) {
fib.push_back(fib[i-1] + fib[i-2]);
}
return fib;
}
template<typename T>
int fibonacciSearch(const vector<T>& arr, const T& target) {
int n = static_cast<int>(arr.size());
// 生成斐波那契数列
vector<int> fib = generateFibonacci(20); // 20足够覆盖大多数情况
// 找到第一个大于等于n的斐波那契数
int k = 0;
while (fib[k] < n) {
k++;
}
// 扩展数组到fib[k]长度
vector<T> temp = arr;
for (int i = n; i < fib[k]; i++) {
temp.push_back(arr[n-1]); // 用最后一个元素填充
}
int left = 0;
int right = fib[k] - 1;
while (left <= right) {
int mid = left + fib[k-1] - 1; // 黄金分割点
if (mid >= n) mid = n - 1; // 防止越界
if (temp[mid] == target) {
return (mid < n) ? mid : n-1; // 如果找到的是填充值,返回最后一个元素索引
} else if (temp[mid] < target) {
left = mid + 1;
k -= 2; // 在右侧查找
} else {
right = mid - 1;
k -= 1; // 在左侧查找
}
}
return -1;
}
// ==================== 5. 哈希查找 ====================
/**
* 时间复杂度: O(1) 平均, O(n) 最坏
* 空间复杂度: O(n)
* 适用: 快速查找,不要求有序
*/
// 简单哈希表实现(链地址法解决冲突)
class SimpleHashTable {
private:
struct HashNode {
int key;
int value;
HashNode* next;
HashNode(int k, int v) : key(k), value(v), next(nullptr) {}
};
vector<HashNode*> table;
int capacity;
int size;
// 简单哈希函数
int hashFunction(int key) {
return key % capacity;
}
public:
SimpleHashTable(int cap = 100) : capacity(cap), size(0) {
table.resize(capacity, nullptr);
}
~SimpleHashTable() {
for (int i = 0; i < capacity; i++) {
HashNode* node = table[i];
while (node) {
HashNode* temp = node;
node = node->next;
delete temp;
}
}
}
// 插入键值对
void insert(int key, int value) {
int index = hashFunction(key);
HashNode* node = table[index];
// 检查是否已存在
while (node) {
if (node->key == key) {
node->value = value; // 更新值
return;
}
node = node->next;
}
// 插入到链表头部
HashNode* newNode = new HashNode(key, value);
newNode->next = table[index];
table[index] = newNode;
size++;
}
// 查找键
int search(int key) {
int index = hashFunction(key);
HashNode* node = table[index];
while (node) {
if (node->key == key) {
return node->value;
}
node = node->next;
}
return -1; // 未找到
}
// 删除键
bool remove(int key) {
int index = hashFunction(key);
HashNode* node = table[index];
HashNode* prev = nullptr;
while (node) {
if (node->key == key) {
if (prev) {
prev->next = node->next;
} else {
table[index] = node->next;
}
delete node;
size--;
return true;
}
prev = node;
node = node->next;
}
return false;
}
int getSize() const { return size; }
int getCapacity() const { return capacity; }
void print() {
for (int i = 0; i < capacity; i++) {
cout << "Bucket " << i << ": ";
HashNode* node = table[i];
while (node) {
cout << "(" << node->key << "," << node->value << ") ";
node = node->next;
}
cout << endl;
}
}
};
// 布隆过滤器(概率性数据结构)
class BloomFilter {
private:
vector<bool> bits;
int size;
vector<int> seeds; // 不同哈希函数的种子
// 简单哈希函数
int hash(const string& key, int seed) {
int hash = 0;
for (char c : key) {
hash = seed * hash + c;
}
return abs(hash) % size;
}
public:
BloomFilter(int n, int numHashes = 3) : size(n) {
bits.resize(n, false);
// 使用不同的种子创建多个哈希函数
for (int i = 0; i < numHashes; i++) {
seeds.push_back(131 + i * 100); // 常见质数
}
}
void insert(const string& key) {
for (int seed : seeds) {
int index = hash(key, seed);
bits[index] = true;
}
}
bool contains(const string& key) {
for (int seed : seeds) {
int index = hash(key, seed);
if (!bits[index]) {
return false; // 一定不存在
}
}
return true; // 可能存在(有假阳性)
}
void printStats() {
int count = 0;
for (bool bit : bits) {
if (bit) count++;
}
cout << "Bloom Filter: " << count << "/" << size << " bits set" << endl;
}
};
// ==================== 6. 二叉搜索树查找 ====================
/**
* 时间复杂度: O(log n) 平均, O(n) 最坏
* 空间复杂度: O(n)
* 适用: 动态查找表
*/
class BinarySearchTree {
private:
struct TreeNode {
int key;
int value;
TreeNode* left;
TreeNode* right;
TreeNode(int k, int v) : key(k), value(v), left(nullptr), right(nullptr) {}
};
TreeNode* root;
int size;
// 插入辅助函数
TreeNode* insertHelper(TreeNode* node, int key, int value) {
if (!node) {
size++;
return new TreeNode(key, value);
}
if (key < node->key) {
node->left = insertHelper(node->left, key, value);
} else if (key > node->key) {
node->right = insertHelper(node->right, key, value);
} else {
node->value = value; // 更新值
}
return node;
}
// 查找辅助函数
TreeNode* searchHelper(TreeNode* node, int key) {
if (!node || node->key == key) {
return node;
}
if (key < node->key) {
return searchHelper(node->left, key);
} else {
return searchHelper(node->right, key);
}
}
// 中序遍历辅助函数
void inorderHelper(TreeNode* node, vector<pair<int, int>>& result) {
if (!node) return;
inorderHelper(node->left, result);
result.push_back({node->key, node->value});
inorderHelper(node->right, result);
}
// 删除辅助函数
TreeNode* deleteHelper(TreeNode* node, int key) {
if (!node) return nullptr;
if (key < node->key) {
node->left = deleteHelper(node->left, key);
} else if (key > node->key) {
node->right = deleteHelper(node->right, key);
} else {
// 找到要删除的节点
if (!node->left) {
TreeNode* temp = node->right;
delete node;
size--;
return temp;
} else if (!node->right) {
TreeNode* temp = node->left;
delete node;
size--;
return temp;
} else {
// 有两个子节点,找到右子树的最小节点
TreeNode* minNode = findMin(node->right);
node->key = minNode->key;
node->value = minNode->value;
node->right = deleteHelper(node->right, minNode->key);
}
}
return node;
}
TreeNode* findMin(TreeNode* node) {
while (node && node->left) {
node = node->left;
}
return node;
}
// 销毁树
void destroyTree(TreeNode* node) {
if (!node) return;
destroyTree(node->left);
destroyTree(node->right);
delete node;
}
public:
BinarySearchTree() : root(nullptr), size(0) {}
~BinarySearchTree() { destroyTree(root); }
void insert(int key, int value) {
root = insertHelper(root, key, value);
}
int search(int key) {
TreeNode* node = searchHelper(root, key);
return node ? node->value : -1;
}
bool remove(int key) {
int oldSize = size;
root = deleteHelper(root, key);
return size < oldSize;
}
vector<pair<int, int>> inorderTraversal() {
vector<pair<int, int>> result;
inorderHelper(root, result);
return result;
}
int getSize() const { return size; }
int getHeight() { return getHeightHelper(root); }
int getHeightHelper(TreeNode* node) {
if (!node) return 0;
return 1 + max(getHeightHelper(node->left), getHeightHelper(node->right));
}
void printTree() {
cout << "Binary Search Tree (size: " << size << "):" << endl;
vector<pair<int, int>> items = inorderTraversal();
for (auto& item : items) {
cout << "(" << item.first << "," << item.second << ") ";
}
cout << endl;
}
};
// ==================== 7. 平衡树查找(AVL树) ====================
/**
* 时间复杂度: O(log n)
* 空间复杂度: O(n)
* 适用: 需要频繁插入删除的动态查找表
*/
class AVLTree {
private:
struct AVLNode {
int key;
int value;
int height;
AVLNode* left;
AVLNode* right;
AVLNode(int k, int v) : key(k), value(v), height(1), left(nullptr), right(nullptr) {}
};
AVLNode* root;
int size;
// 获取节点高度
int getHeight(AVLNode* node) {
return node ? node->height : 0;
}
// 获取平衡因子
int getBalance(AVLNode* node) {
return node ? getHeight(node->left) - getHeight(node->right) : 0;
}
// 右旋
AVLNode* rightRotate(AVLNode* y) {
AVLNode* x = y->left;
AVLNode* T2 = x->right;
// 旋转
x->right = y;
y->left = T2;
// 更新高度
y->height = 1 + max(getHeight(y->left), getHeight(y->right));
x->height = 1 + max(getHeight(x->left), getHeight(x->right));
return x;
}
// 左旋
AVLNode* leftRotate(AVLNode* x) {
AVLNode* y = x->right;
AVLNode* T2 = y->left;
// 旋转
y->left = x;
x->right = T2;
// 更新高度
x->height = 1 + max(getHeight(x->left), getHeight(x->right));
y->height = 1 + max(getHeight(y->left), getHeight(y->right));
return y;
}
// 插入辅助函数
AVLNode* insertHelper(AVLNode* node, int key, int value) {
if (!node) {
size++;
return new AVLNode(key, value);
}
if (key < node->key) {
node->left = insertHelper(node->left, key, value);
} else if (key > node->key) {
node->right = insertHelper(node->right, key, value);
} else {
node->value = value; // 更新值
return node;
}
// 更新高度
node->height = 1 + max(getHeight(node->left), getHeight(node->right));
// 获取平衡因子
int balance = getBalance(node);
// 平衡调整
// 左左情况
if (balance > 1 && key < node->left->key) {
return rightRotate(node);
}
// 右右情况
if (balance < -1 && key > node->right->key) {
return leftRotate(node);
}
// 左右情况
if (balance > 1 && key > node->left->key) {
node->left = leftRotate(node->left);
return rightRotate(node);
}
// 右左情况
if (balance < -1 && key < node->right->key) {
node->right = rightRotate(node->right);
return leftRotate(node);
}
return node;
}
// 查找辅助函数
AVLNode* searchHelper(AVLNode* node, int key) {
if (!node || node->key == key) {
return node;
}
if (key < node->key) {
return searchHelper(node->left, key);
} else {
return searchHelper(node->right, key);
}
}
// 销毁树
void destroyTree(AVLNode* node) {
if (!node) return;
destroyTree(node->left);
destroyTree(node->right);
delete node;
}
public:
AVLTree() : root(nullptr), size(0) {}
~AVLTree() { destroyTree(root); }
void insert(int key, int value) {
root = insertHelper(root, key, value);
}
int search(int key) {
AVLNode* node = searchHelper(root, key);
return node ? node->value : -1;
}
int getSize() const { return size; }
int getHeight() { return getHeight(root); }
bool isBalanced() {
return isBalancedHelper(root);
}
bool isBalancedHelper(AVLNode* node) {
if (!node) return true;
int balance = getBalance(node);
if (abs(balance) > 1) return false;
return isBalancedHelper(node->left) && isBalancedHelper(node->right);
}
void printInfo() {
cout << "AVL Tree - Size: " << size
<< ", Height: " << getHeight()
<< ", Balanced: " << (isBalanced() ? "Yes" : "No") << endl;
}
};
// ==================== 8. B树查找 ====================
/**
* 时间复杂度: O(log n)
* 空间复杂度: O(n)
* 适用: 磁盘存储,数据库索引
*/
class BTree {
private:
struct BTreeNode {
vector<int> keys;
vector<BTreeNode*> children;
bool leaf;
int degree; // 最小度数
BTreeNode(int t, bool isLeaf) : leaf(isLeaf), degree(t) {}
// 遍历节点
void traverse() {
int i;
for (i = 0; i < keys.size(); i++) {
if (!leaf) {
children[i]->traverse();
}
cout << keys[i] << " ";
}
if (!leaf) {
children[i]->traverse();
}
}
// 在节点中查找键
int searchKey(int k) {
int idx = 0;
while (idx < keys.size() && keys[idx] < k) {
idx++;
}
return idx;
}
};
BTreeNode* root;
int degree; // 最小度数
// 插入辅助函数
void insertNonFull(BTreeNode* node, int k) {
int i = node->keys.size() - 1;
if (node->leaf) {
// 如果是叶节点,直接插入
node->keys.push_back(0); // 扩展数组
while (i >= 0 && node->keys[i] > k) {
node->keys[i+1] = node->keys[i];
i--;
}
node->keys[i+1] = k;
} else {
// 找到要插入的子节点
while (i >= 0 && node->keys[i] > k) {
i--;
}
// 如果子节点已满,先分裂
if (node->children[i+1]->keys.size() == 2*degree - 1) {
splitChild(node, i+1, node->children[i+1]);
if (node->keys[i+1] < k) {
i++;
}
}
insertNonFull(node->children[i+1], k);
}
}
// 分裂子节点
void splitChild(BTreeNode* parent, int i, BTreeNode* child) {
BTreeNode* newChild = new BTreeNode(degree, child->leaf);
// 移动后半部分键到新节点
for (int j = 0; j < degree - 1; j++) {
newChild->keys.push_back(child->keys[j + degree]);
}
// 如果不是叶节点,移动子节点指针
if (!child->leaf) {
for (int j = 0; j < degree; j++) {
newChild->children.push_back(child->children[j + degree]);
}
}
// 调整原节点的大小
child->keys.resize(degree - 1);
// 在父节点中为新子节点腾出空间
parent->children.insert(parent->children.begin() + i + 1, newChild);
parent->keys.insert(parent->keys.begin() + i, child->keys[degree - 1]);
}
// 查找辅助函数
pair<BTreeNode*, int> searchHelper(BTreeNode* node, int k) {
if (!node) return {nullptr, -1};
int i = 0;
while (i < node->keys.size() && k > node->keys[i]) {
i++;
}
if (i < node->keys.size() && node->keys[i] == k) {
return {node, i};
}
if (node->leaf) {
return {nullptr, -1};
}
return searchHelper(node->children[i], k);
}
// 销毁树
void destroyTree(BTreeNode* node) {
if (!node) return;
if (!node->leaf) {
for (auto child : node->children) {
destroyTree(child);
}
}
delete node;
}
public:
BTree(int t) : root(nullptr), degree(t) {}
~BTree() { destroyTree(root); }
// 遍历B树
void traverse() {
if (root) {
root->traverse();
cout << endl;
}
}
// 查找键
int search(int k) {
auto result = searchHelper(root, k);
if (result.first) {
return result.first->keys[result.second];
}
return -1;
}
// 插入键
void insert(int k) {
if (!root) {
root = new BTreeNode(degree, true);
root->keys.push_back(k);
} else {
if (root->keys.size() == 2*degree - 1) {
// 根节点已满,需要分裂
BTreeNode* newRoot = new BTreeNode(degree, false);
newRoot->children.push_back(root);
splitChild(newRoot, 0, root);
// 决定插入到哪个子节点
int i = 0;
if (newRoot->keys[0] < k) {
i++;
}
insertNonFull(newRoot->children[i], k);
root = newRoot;
} else {
insertNonFull(root, k);
}
}
}
void printInfo() {
cout << "B-Tree (degree=" << degree << ")" << endl;
cout << "Inorder traversal: ";
traverse();
}
};
// ==================== 测试函数 ====================
void testSearchAlgorithm() {
cout << "=== 查找算法测试 ===" << endl;
// 生成测试数据
const int n = 100000;
vector<int> arr = generateSortedArray(n);
// 测试目标
int target = 50000; // 存在的目标
int missingTarget = 50001; // 不存在的目标(奇数)
cout << "数组大小: " << n << endl;
cout << "目标值: " << target << " (存在), " << missingTarget << " (不存在)" << endl;
// 1. 顺序查找
cout << "\n1. 顺序查找测试:" << endl;
clock_t start = clock();
int idx1 = sequentialSearch(arr, target);
clock_t end = clock();
cout << " 查找 " << target << ": 索引=" << idx1
<< ", 时间=" << fixed << setprecision(3)
<< double(end-start)/CLOCKS_PER_SEC*1000 << "ms" << endl;
start = clock();
int idx2 = sequentialSearch(arr, missingTarget);
end = clock();
cout << " 查找 " << missingTarget << ": 索引=" << idx2
<< ", 时间=" << fixed << setprecision(3)
<< double(end-start)/CLOCKS_PER_SEC*1000 << "ms" << endl;
// 2. 二分查找
cout << "\n2. 二分查找测试:" << endl;
start = clock();
int idx3 = binarySearchIterative(arr, target);
end = clock();
cout << " 迭代查找 " << target << ": 索引=" << idx3
<< ", 时间=" << fixed << setprecision(6)
<< double(end-start)/CLOCKS_PER_SEC*1000 << "ms" << endl;
start = clock();
int idx4 = binarySearchRecursive(arr, target);
end = clock();
cout << " 递归查找 " << target << ": 索引=" << idx4
<< ", 时间=" << fixed << setprecision(6)
<< double(end-start)/CLOCKS_PER_SEC*1000 << "ms" << endl;
// 3. 插值查找
cout << "\n3. 插值查找测试:" << endl;
start = clock();
int idx5 = interpolationSearch(arr, target);
end = clock();
cout << " 查找 " << target << ": 索引=" << idx5
<< ", 时间=" << fixed << setprecision(6)
<< double(end-start)/CLOCKS_PER_SEC*1000 << "ms" << endl;
// 4. 斐波那契查找
cout << "\n4. 斐波那契查找测试:" << endl;
start = clock();
int idx6 = fibonacciSearch(arr, target);
end = clock();
cout << " 查找 " << target << ": 索引=" << idx6
<< ", 时间=" << fixed << setprecision(6)
<< double(end-start)/CLOCKS_PER_SEC*1000 << "ms" << endl;
// 5. 哈希查找
cout << "\n5. 哈希查找测试:" << endl;
SimpleHashTable hashTable(1000);
for (int i = 0; i < 1000; i++) {
hashTable.insert(i, i*10);
}
start = clock();
int val1 = hashTable.search(500);
end = clock();
cout << " 查找键500: 值=" << val1
<< ", 时间=" << fixed << setprecision(6)
<< double(end-start)/CLOCKS_PER_SEC*1000 << "ms" << endl;
// 6. 二叉搜索树查找
cout << "\n6. 二叉搜索树测试:" << endl;
BinarySearchTree bst;
for (int i = 0; i < 1000; i++) {
bst.insert(i, i*10);
}
start = clock();
int val2 = bst.search(500);
end = clock();
cout << " 查找键500: 值=" << val2
<< ", 树高度=" << bst.getHeight()
<< ", 时间=" << fixed << setprecision(6)
<< double(end-start)/CLOCKS_PER_SEC*1000 << "ms" << endl;
// 7. AVL树查找
cout << "\n7. AVL树测试:" << endl;
AVLTree avl;
for (int i = 0; i < 1000; i++) {
avl.insert(i, i*10);
}
start = clock();
int val3 = avl.search(500);
end = clock();
cout << " 查找键500: 值=" << val3
<< ", 树高度=" << avl.getHeight()
<< ", 时间=" << fixed << setprecision(6)
<< double(end-start)/CLOCKS_PER_SEC*1000 << "ms" << endl;
// 8. B树查找
cout << "\n8. B树测试:" << endl;
BTree btree(3);
for (int i = 0; i < 50; i++) {
btree.insert(i*2);
}
start = clock();
int val4 = btree.search(50);
end = clock();
cout << " 查找键50: 值=" << val4
<< ", 时间=" << fixed << setprecision(6)
<< double(end-start)/CLOCKS_PER_SEC*1000 << "ms" << endl;
// 布隆过滤器测试
cout << "\n9. 布隆过滤器测试:" << endl;
BloomFilter bloom(1000, 3);
bloom.insert("apple");
bloom.insert("banana");
bloom.insert("cherry");
cout << " 查询 'apple': " << (bloom.contains("apple") ? "可能存在" : "一定不存在") << endl;
cout << " 查询 'orange': " << (bloom.contains("orange") ? "可能存在" : "一定不存在") << endl;
bloom.printStats();
}
int main() {
srand(time(0));
// 运行测试
testSearchAlgorithm();
// 额外演示
cout << "\n=== 额外演示 ===" << endl;
// 二分查找变体演示
vector<int> arr = {1, 2, 2, 2, 3, 3, 4, 5, 5, 6};
cout << "\n数组: ";
printArray(arr);
int target = 2;
cout << "查找 " << target << ":" << endl;
cout << " 第一个位置: " << binarySearchFirst(arr, target) << endl;
cout << " 最后一个位置: " << binarySearchLast(arr, target) << endl;
cout << " 第一个>=2的位置: " << binarySearchLowerBound(arr, target) << endl;
cout << " 第一个>2的位置: " << binarySearchUpperBound(arr, target) << endl;
return 0;
}
算法性能对比表
| 算法 | 平均时间 | 最坏时间 | 空间 | 要求 | 适用场景 |
|---|---|---|---|---|---|
| 顺序查找 | O(n) | O(n) | O(1) | 无 | 无序小数据,简单实现 |
| 二分查找 | O(log n) | O(log n) | O(1) | 有序 | 静态有序数组 |
| 插值查找 | O(log log n) | O(n) | O(1) | 有序均匀分布 | 字典、电话簿 |
| 斐波那契查找 | O(log n) | O(log n) | O(1) | 有序 | 避免除法运算 |
| 哈希查找 | O(1) | O(n) | O(n) | 无 | 快速查找,键值存储 |
| 二叉搜索树查找 | O(log n) | O(n) | O(n) | 可比较 | 动态查找表 |
| AVL树查找 | O(log n) | O(log n) | O(n) | 可比较 | 频繁插入删除 |
| B树查找 | O(log n) | O(log n) | O(n) | 可比较 | 数据库索引,磁盘存储 |
算法选择指南
-
数据是否有序?
- 是 → 二分查找、插值查找、斐波那契查找
- 否 → 顺序查找、哈希查找
-
数据规模多大?
- 小数据 (<1000) → 顺序查找、二分查找
- 大数据 (≥1000) → 哈希、树结构
-
查找频率如何?
- 频繁查找 → 哈希表、建立索引
- 偶尔查找 → 顺序查找
-
是否需要动态更新?
- 静态数据 → 二分查找
- 动态数据 → 二叉搜索树、AVL树、B树
-
内存是否充足?
- 内存充足 → 哈希表
- 内存受限 → 树结构
-
是否需要范围查询?
- 需要 → 树结构
- 不需要 → 哈希表
编译运行
# 编译
g++ -std=c++11 -O2 search_algorithms.cpp -o search
# 运行
./search
输出示例
=== 查找算法测试 ===
数组大小: 100000
目标值: 50000 (存在), 50001 (不存在)
1. 顺序查找测试:
查找 50000: 索引=25000, 时间=2.456ms
查找 50001: 索引=-1, 时间=4.123ms
2. 二分查找测试:
迭代查找 50000: 索引=25000, 时间=0.001ms
递归查找 50000: 索引=25000, 时间=0.002ms
3. 插值查找测试:
查找 50000: 索引=25000, 时间=0.001ms
4. 斐波那契查找测试:
查找 50000: 索引=25000, 时间=0.002ms
5. 哈希查找测试:
查找键500: 值=5000, 时间=0.001ms
6. 二叉搜索树测试:
查找键500: 值=5000, 树高度=20, 时间=0.002ms
7. AVL树测试:
查找键500: 值=5000, 树高度=10, 时间=0.001ms
8. B树测试:
查找键50: 值=50, 时间=0.001ms
9. 布隆过滤器测试:
查询 'apple': 可能存在
查询 'orange': 一定不存在
Bloom Filter: 12/1000 bits set
这个实现包含了8种经典查找算法的完整C++代码,涵盖从简单到复杂、从内存到磁盘的各种查找场景。每种算法都有详细的注释和性能分析,可以直接编译运行测试。