本文根据《大话数据结构》一书,实现了Java版的顺序查找、折半查找、插值查找、斐波那契查找

注:为与书一致,记录均从下标为1开始。

顺序表查找

顺序查找

 顺序查找(Sequential Search):从第一个到最后一个记录依次与给定值比较,若相等则查找成功。

  顺序查找优化:设置哨兵,可以避免每次循环都判断是否越界。在数据量很多时能提高效率。

  时间复杂度:O(n),n为记录的数。

以下为顺序查找算法及其优化的Java代码:

package Sequential_Search;
/**
* 顺序表查找
* 数组下标为0的位置不用来储存实际内容
* @author Yongh
*
*/
public class Sequential_Search {
/*
* 顺序查找
*/
public int seqSearch(int[] arr,int key) {
int n=arr.length;
for(int i=1;i<n;i++) { //i从1开始
if(key==arr[i])
return i;
}
return 0;
}
/*
* 顺序查找优化,带哨兵
*/
public int seqSearch2(int[] arr,int key) {
int i=arr.length-1;
arr[0]=key; //将arr[0]设为哨兵
while(arr[i]!=key)
i--;
return i; //返回0说明查找失败
} public static void main(String[] args) {
int[] arr = {0,45,68,32,15};
Sequential_Search aSearch = new Sequential_Search();
System.out.println(aSearch.seqSearch(arr, 15));
System.out.println(aSearch.seqSearch(arr, 45));
}
}

 


Sequential_Search

有序表查找

折半查找(二分查找)

折半查找,又称作二分查找。必须满足两个前提:

1.存储结构必须是顺序存储 
2.关键码必须有序排列

假设数据按升序排列。从中间项与关键值(key)开始对比,若关键值(key)>中间值,则在右半区间继续查找,反之则左半区间继续查找。以此类推,直至找到匹配值,或者查找内无记录,查找失败。

时间复杂度:O(logn),可从二叉树的性质4推得。

折半查找的Java实现代码:

package OrderedTable_Search;
/**
* 折半查找
* @author Yongh
*
*/
public class BinarySearch {
public int binarySearch(int[] arr,int n,int key) {
int low=1;
int high=n;
while(low<=high) {
int mid = (low+high)/2;
if(arr[mid]<key)
low=mid+1; //要+1
else if(arr[mid]>key)
high=mid-1; //要-1
else
return mid;
}
return 0;
} public static void main(String[] args) {
int[] arr = {0,1,16,24,35,47,59,62,73,88,99};
int n=arr.length-1;
int key=62;
BinarySearch aSearch = new BinarySearch();
System.out.println(aSearch.binarySearch(arr, n, key));
}
}

  


BinarySearch

插值查找

对于表长较大,关键字分布比较均匀的查找表来说,可以采用插值查找:

  将折半查找中代码的第12行

  改进为:

  改进后的第12行代码如下:

int mid = low + (high - low) * (key - arr[low]) / (arr[high] - arr[low]);/*插值*/

  注意:关键字分布不均匀的情况下,该方法不一定比折半查找要好。

斐波那契查找

  斐波那契数列如下所示:

  斐波那契查找原理与前两种相似,仅仅改变了中间结点(mid)的位置,mid不再是中间或插值得到,而是位于黄金分割点附近,即mid=low+F(k-1)-1(F代表斐波那契数列),如下图所示:

  对F(k-1)-1的理解:

  由斐波那契数列 F[k]=F[k-1]+F[k-2] 的性质,可以得到 (F[k]-1)=(F[k-1]-1)+(F[k-2]-1)+1 。该式说明:只要顺序表的长度为F[k]-1,则可以将该表分成长度为F[k-1]-1F[k-2]-1的两段,即如上图所示。从而中间位置为mid=low+F(k-1)-1

  类似的,每一子段也可以用相同的方式分割,从而方便编程。

  但顺序表长度n不一定刚好等于F[k]-1,所以需要将原来的顺序表长度n增加至F[k]-1。这里的k值只要能使得F[k]-1恰好大于或等于n即可,由以下代码得到:

while(n>fib(k)-1)
k++;

  顺序表长度增加后,新增的位置(从n+1到F[k]-1位置),都赋为n位置的值即可。

  时间复杂度:O(logn)

以下为具体的Java代码,还有不理解的地方可看对应处的注释:

package OrderedTable_Search;
/**
* 斐波那契查找
* 下标为0位置不存储记录
* 顺便编写了斐波那契数列的代码
* @author Yongh
*
*/
public class FibonacciSearch {
/*
* 斐波那契数列
* 采用递归
*/
public static int fib(int n) {
if(n==0)
return 0;
if(n==1)
return 1;
return fib(n-1)+fib(n-2);
} /*
* 斐波那契数列
* 不采用递归
*/
public static int fib2(int n) {
int a=0;
int b=1;
if(n==0)
return a;
if(n==1)
return b;
int c=0;
for(int i=2;i<=n;i++) {
c=a+b;
a=b;
b=c;
}
return c;
} /*
* 斐波那契查找
*/
public static int fibSearch(int[] arr,int n,int key) {
int low=1; //记录从1开始
int high=n; //high不用等于fib(k)-1,效果相同
int mid; int k=0;
while(n>fib(k)-1) //获取k值
k++;
int[] temp = new int[fib(k)]; //因为无法直接对原数组arr[]增加长度,所以定义一个新的数组
System.arraycopy(arr, 0, temp, 0, arr.length); //采用System.arraycopy()进行数组间的赋值
for(int i=n+1;i<=fib(k)-1;i++) //对数组中新增的位置进行赋值
temp[i]=temp[n]; while(low<=high) {
mid=low+fib(k-1)-1;
if(temp[mid]>key) {
high=mid-1;
k=k-1; //对应上图中的左段,长度F[k-1]-1
}else if(temp[mid]<key) {
low=mid+1;
k=k-2; //对应上图中的右端,长度F[k-2]-1
}else {
if(mid<=n)
return mid;
else
return n; //当mid位于新增的数组中时,返回n
}
}
return 0;
}
public static void main(String[] args) {
int[] arr = {0,1,16,24,35,47,59,62,73,88,99};
int n=10;
int key=59;
System.out.println(fibSearch(arr, n, key)); //输出结果为:6
}
}

  

【Java】 大话数据结构(10) 查找算法(1)(顺序、二分、插值、斐波那契查找)的更多相关文章

  1. python实现斐波那契查找

    通过在网上找教程解释和看书,总结出一套比较简单易懂的代码实现. 斐波那契查找和二分查找一样,针对的是有序序列,在此前提下: # 先创建一个Fibonacci函数 fib = lambda n: n i ...

  2. 斐波那契查找(Fibonacci Search)

    斐波那契查找 斐波那契查找就是在二分查找的基础上根据斐波那契数列进行分割的.   在斐波那契数列找一个等于略大于查找表中元素个数的数F[n],将原查找表扩展为长度为F[n](如果要补充元素,则补充重复 ...

  3. Java算法求最大最小值,冒泡排序,斐波纳契数列一些经典算法<不断更新中>

    清明在家,无聊,把一些经典的算法总结了一下. 一.求最大,最小值 Scanner input=new Scanner(System.in); int[] a={21,31,4,2,766,345,2, ...

  4. java程序员到底该不该了解一点算法(一个简单的递归计算斐波那契数列的案例说明算法对程序的重要性)

    为什么说 “算法是程序的灵魂这句话一点也不为过”,递归计算斐波那契数列的第50项是多少? 方案一:只是单纯的使用递归,递归的那个方法被执行了250多亿次,耗时1分钟还要多. 方案二:用一个map去存储 ...

  5. 算法笔记_173:历届试题 斐波那契(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 问题描述 斐波那契数列大家都非常熟悉.它的定义是: f(x) = 1 .... (x=1,2) f(x) = f(x-1) + f(x-2) ... ...

  6. 10、end关键字和Fibonacci series: 斐波纳契数列

    # Fibonacci series: 斐波纳契数列 # 两个元素的总和确定了下一个数 a, b = 0, 1 #复合赋值表达式,a,b同时赋值0和1 while b < 10: print(b ...

  7. 算法小节(一)——斐波那契数列(java实现)

    看到公司的笔试题中有一道题让写斐波那契数列,自己忙里偷闲写了一下 什么是斐波那契数列:斐波那契数列指的是这样一个数列 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...

  8. python 斐波那契查找

    def fibonacci_search(lis, key): # F = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987 ...

  9. 查找算法(4)--Fibonacci search--斐波那契查找

    1.斐波那契查找 (1)说明 在介绍斐波那契查找算法之前,我们先介绍一下很它紧密相连并且大家都熟知的一个概念——黄金分割. 黄金比例又称黄金分割,是指事物各部分间一定的数学比例关系,即将整体一分为二, ...

随机推荐

  1. bzoj 4464 : [Jsoi2013]旅行时的困惑

    网络流建图. 从S向每个点连边,从每个点向T连边. 每条树边反向连一条下界为1,上界inf的边. 跑最小流. 注意加当前弧优化. #include<cstdio> #include< ...

  2. 洛谷P1280 尼克的任务

    这个DP气死我了.....写的时候脑子比较迟钝于是爆0了好几次,最后还是我旁边的AKIOI巨佬告诉我解法才会做. 我一开始设计的状态是f[i]表示i时刻正在休息,从1到i的最长休息时间. 然后经历了各 ...

  3. 稳定排序nlogn之归并排序_一维,二维

    稳定排序nlogn之归并排序_一维,二维 稳定排序:排序时间稳定的排序 稳定排序包括:归并排序(nlogn),基数排序[设待排序列为n个记录,d个关键码,关键码的取值范围为radix,则进行链式基数排 ...

  4. ubuntu,centor 安装apache bench

    ab全称为:apache bench. 是apache自带的压力测试工具.ab非常实用,它不仅可以对apache服务器进行网站访问压力测试,也可以对或其它类型的服务器进行压力测试.比如nginx.to ...

  5. Linux shell 日期,时间相关的命令

    在shell脚本中,经常要用到跟获取日期相关的东西,这里记录一下Linux shell 获取日期的方法 获取当前日期:today=`date +"%Y-%m-%d"` 获取昨天的日 ...

  6. JAVA中日期转换和日期计算的方法

    日期的格式有很多形式,在使用过程中经常需要转换,下面是各种类型转换的使用例子以及日期计算方法的例子. 一.不同格式日期相互转换方法 public class TestDateConvertUtil { ...

  7. bzoj千题计划222:bzoj2329: [HNOI2011]括号修复(fhq treap)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2329 需要改变的括号序列一定长这样 :)))((( 最少改变次数= 多余的‘)’/2 [上取整] + ...

  8. [C]语法, 知识点总结(一. 进制, 格式化输入/出, 指针)

    进制 概念: n进制, 最大的数是n-1, 逢n进1位. 数据类型 概念: 其实就是占的位数不同, 转换到计算机当中都是0和1. 常用: 类型名 占字节数 描述 char 1字节=8个二进制位 字符类 ...

  9. Red Pen - 快速高效的获取设计项目的反馈

    Red Pen 让设计师能够快速,高效的从你的同事和客户获取反馈.只需要简单的拖放图像到 Red Pen 主页,然后把生成的链接分享给你的同事或者客户.他们打开链接就能看到设计稿,并给予实时的反馈,所 ...

  10. # 20155337 2016-2017-2 《Java程序设计》第六周学习总结

    20155337 2016-2017-2 <Java程序设计>第六周学习总结 教材学习内容总结 •串流(Stream): 数据有来源及目的地,衔接两者的是串流对象.如果要将数据从来源取出, ...