算法-查找
学习并记录下查找算法,方便回顾。
查找算法 | 平均时间复杂度 | 空间复杂度 | 查找条件 ---|---|---|+++ 顺序查找 | O(n) | O(1) | 无序 二分查找(折半查找)| O(log2n)| O(1) | 有序 分块查找(索引顺序查找)| | | 插值查找 | O(log2(log2n)) | O(1) | 有序 斐波那契查找 | O(log2n) | O(1) | 有序 哈希查找| O(1) | O(n) | 无序 二叉查找树(二叉搜索树查找) |O(log2n) | | 红黑树|O(log2n) | | 2-3树 | O(log2n - log3n) | | B树/B+树 |O(log2n) | |
顺序查找
顺序查找适合于存储结构为顺序存储或链接存储的线性表,属于无序查找算法。
int SeqSearch(vector<int> &v, int val){
for(int i = 0; i < v.size(); ++i){
if(v[i] == val)return i;
}
return -1;
}
二分查找
元素必须是有序的,如果是无序的则要先进行排序操作,属于有序查找算法。
//迭代方式
int BinarySearch(vector<int> &v, int val, int low, int high){
if(v.size() <= 0)return -1;
while(low <= high){
int mid = low + (high - low)/2;
if(v[mid] == val)return mid;
else if(v[mid] > val)high = mid - 1;
else low = mid + 1;
}
return -1;
}
//递归方式
int BinarySearch(vector<int> &v, int val, int low, int high){
if(v.size() <= 0)return -1;
if(low > high)
return -1;
int mid = low + (high - low)/2;
if(v[mid] == val)
return mid;
else if(v[mid] > val)
return BinarySearch(v, val, low, mid - 1);
else
return BinarySearch(v, val, mid + 1, high);
}
分块查找
插值查找
基于二分查找算法,将查找点的选择改进为自适应选择,可以提高查找效率,属于有序查找。
二分查找:$mid = low + {1 \over 2}(high - low) $
插值查找:$mid = low + {val - v[low] \over v[high] - v[low]}(high - low) $
//迭代方式
int InsertSearch(vector<int> &v, int val, int low, int high){
if(v.size() <= 0)return -1;
while(low <= high){
int mid = low + (val - v[low])/(v[high] - v[low]) * (high - low);
if(v[mid] == val)return mid;
else if(v[mid] > val)high = mid - 1;
else low = mid + 1;
}
return -1;
}
//递归方式
int InsertSearch(vector<int> &v, int val, int low, int high){
if(v.size() <= 0)return -1;
if(low > high)return -1;
int mid = low + (val - v[low])/(v[high] - v[low]) * (high - low);
if(v[mid] == val)
return mid;
else if(v[mid] > val)
return InsertSearch(v, val, low, mid - 1);
else
return InsertSearch(v, val, mid + 1, high);
}
斐波那契查找
基于二分查找算法,通过运用黄金比例的概念选择点进行查找,提高查找效率,属于有序查找算法。
随着斐波那契数列的递增,前后两个数的比值会越来越接近0.618,利用这个特性,将黄金比例运用到查找技术中。
要求开始表中记录的个数为某个斐波那契数小1,及n=F(k)-1
int f[20];
void Fibonacci(){
f[0] = 0;
f[1] = 1;
for(int i = 2; i < 20; ++i)
f[i] = f[i-1] + f[i-2];
}
int FibonacciSearch(vector<int> &v, int n, int val){
int low = 0;
int high = n - 1;
int k = 0;
while(n > f[k] - 1)++k;
vector<int> temp(v);
for(int i = n; i < f[k] - 1; ++i)
temp.push_back(v[n-1]);
while(low <= high){
int mid = low + f[k-1] - 1;
if(val < temp[mid]){
high = mid - 1;
k -= 1;
}
else if(val > temp[mid]){
low = mid + 1;
k -= 2;
}
else{ //判断是否扩展的数值
if(mid < n)return mid;
else return n - 1;
}
}
return -1;
}
二叉树查找
在二叉搜索树b中查找x的过程为:
- 若b是空树,则搜索失败,否则:
- 若x等于b的根节点的数据域之值,则查找成功;否则:
- 若x小于b的根节点的数据域之值,则搜索左子树;否则:
- 查找右子树
BSTNode *BSTSearch(BSTNode *node, int val){
while(node != NULL){
if(val < node -> val)node = node -> left;
else if(val > node -> val)node = node -> right;
else return node;
}
return nullptr;
}