一、查找算法概述
1. 查找算法
- 查找:根据给定的值,在查找表中确定一个关键字等于给定值的元素
- 分类:
- 静态查找和动态查找
- 无序查找和有序查找
- 无序查找:被查找数列有序无序均可
- 有序查找:被查找数列必须有序
2. 常见查找算法
二、常见查找算法
1. 顺序查找
- 思路
- 一种无序查找算法。从数据结构线性表一端开始,顺序扫描,将扫描得到的结点关键字与给定值进行比较
- 复杂度:
public boolean sequenceSearch(List<Integer> list, int target){
int size = list.size();
for(int i = 0; i < size; i++){
if(target == list.get(i)){
return true;
}
}
return false;
}
2. 二分查找
- 思路
- 一种有序查找算法。将给定值与中间结点的关键词比较,相等查找成功,不相等则根据比较结果确定查找那个子表,递归进行
- 时间复杂度
- 特点
- 适用于有序、静态查找,频繁插入和删除的数据集不适用
public boolean binarySearch(List<Integer> list, int target){
int low = 0, high = list.size() - 1, mid;
while(low <= high){
mid = (low + high) / 2;
if(target == list.get(mid)){
return true;
} else if(list.get(mid) < target){
left = mid + 1;
} else {
right = mid - 1;
}
}
return false;
}
3. 插值查找
- 思路
- 一种有序查找算法,是对二分查找算法的改进,根据关键字在有序表中所处的位置进行查找,而不是直接一般的位置
- 二分查找:mid = low + 1/2(high - low)
- 插值查找:mid = low + (key - a[low])/(a[high] - a[low])*(high - low)
- 时间复杂度
- 特点
- 对于表长较大,关键字分布均匀的查找表,插值查找的平均性能比二分查找好得多;反之则未必
public boolean interplotSearch(List<Integer> list, int target){
if(list.isEmpty()){
return false;
}
int low = 0, high = list.size() - 1, mid;
while(low <= high){
mid = low + (target - list.get(low)) / (list.get(high)- list.get(low)) * (high - low);
if(target == list.get(mid)){
return true;
} else if(list.get(mid) < target){
low = mid + 1;
} else {
high = mid - 1;
}
}
return false;
}
4. 斐波那契查找
- 思路:
- 一种有序查找算法,也是对二分查找的改进,按照黄金分割比例进行查找
- 声明斐波那契数列为F(n)
- 数列为:1,1,2,3,5,8,13,21,34…,随着数列递增,前后两个数的比值越接近0.618
- 数列满足:F(n) = F(n-1) + F(n-2)
- 要求查找序列的元素个数为某个斐波那契数 - 1,即n = F(k) - 1
- 将给定值与F(k-1)位置的记录进行比较,mid = low + F(k-1) - 1
- 相等即查找成功
- 给定值大于mid位置的值,low = mid + 1,k = k - 2
- 给定值小于mid位置的值,high = mid - 1, k = k - 1
![斐波那契查找](https://i-blog.csdnimg.cn/blog_migrate/1296fd1f20ba9086446d659ed88ac6c6.png#pic_center)
- 时间复杂度
public boolean fibonaccSearch(List<Integer> list, int target){
if(list.isEmpty()){
return false;
}
int oldLen = list.size();
List<Integer> fibs = getFibonacc(oldLen);
int newLen = fibs.get(fibs.size() - 1) - 1;
List<Integer> newList = new ArrayList<>(newLen);
newList.addAll(list);
for(int i = oldLen; i < newLen; i++){
newList.add(list.get(oldLen - 1));
}
int index = fibs.size() - 1, low = 0, high = newLen - 1, mid;
while(low <= high){
mid = low + fibs.get(index - 1) - 1;
if(mid >= newLen){
mid = newLen - 1;
}
if(target == newList.get(mid)){
return true;
} else if(newList.get(mid) < target){
low = mid + 1;
index -= 2;
} else {
high = mid - 1;
index--;
}
}
return false;
}
public List<Integer> getFibonacc(int len){
List<Integer> fibs = new ArrayList<>();
int tmp = 1, index = 0;
while(len > tmp - 1){
if(index == 0){
tmp = 1;
} else if(index == 1){
tmp = 1;
} else {
tmp = fibs.get(index - 1) + fibs.get(index - 2);
}
fibs.add(tmp);
index++;
}
return fibs;
}
public static void main(String[] args) {
Search search = new Search();
List<Integer> fibonacc = search.getFibonacc(0);
search.fibonaccSearch(Arrays.asList(1), 1);
}