我编写了代码来实现线性搜索(从数组的开头开始)和反向线性搜索(从数组的结尾开始)。现在,当我对1000个数字,1000次(每次使用不同的键)的样本运行程序时,这是累积结果。
总时间LS:814632
总时间RLS:581558
我想知道为什么我们在执行时间上有这么明显的差异。我用system.nanoTime()来检查时间。我认为,考虑到1000的大量分布(将两个函数称为1000次),时间差异不应该太大,因为密钥可能属于1000个索引中的任何一个。
public static void main(String[] args) throws AWTException, Exception {
long val[][] = new long[1000][3];
for(int i=0;i<1000;i++)
{
val[i]= testMethod();
}
long ls=0;
long rls=0;
long bls=0;
for(int i=0;i<1000;i++)
{
ls= ls+val[i][0];
rls=rls+val[i][1];
bls=bls+val[i][2];
}
System.out.println("Total Time LS :" + ls);
System.out.println("Total time RLS : " + rls);
System.out.println("Total time BLS : " + bls);
}
public static long[] testMethod()
{ long[] val=new long[3];
int[] arr= new int[1000];
Random r = new Random();
for(int i=0;i<1000;i++)
{
arr[i]=r.nextInt()%99999;
}
int i= Math.abs(r.nextInt()%1000);
int key =arr[i] ;
// int key = arr[900];
// System.out.println(i);
long sysTime1=System.nanoTime();
int pos_LS= LS(arr,key);
long sysTime2=System.nanoTime();
long t=sysTime2-sysTime1;
val[0]=t;
// System.out.println("LS Time : " + t);
sysTime1=System.nanoTime();
int pos_RLS=RLS(arr,key);
sysTime2=System.nanoTime();
t=sysTime2-sysTime1;
// System.out.println("RLS Time : " + t);
val[1]=t;
sysTime1=System.nanoTime();
int pos_BLS=BLS(arr,key);
sysTime2=System.nanoTime();
t=sysTime2-sysTime1;
// System.out.println("BLS Time : " + t);
val[2]=t;
return val;
}
public static int LS(int[] arr, int key)
{
for(int i=0;i<arr.length;i++)
{
if(arr[i]==key)
{
return i;
}
}
return -1;
}
public static int RLS(int[] arr, int key)
{
for(int i=arr.length-1;i>=0;i--)
{
if(arr[i]==key)
{
return i;
}
}
return -1;
}
public static int BLS(int[] arr, int key)
{
int len=arr.length;
for(int i=0;i<len/2;i++)
{
if(arr[i]==key || arr[len-1-i]==key)
{
if(arr[i]==key)
{
return i;
}
else
{
return len-i-1;
}
}
}
return -1;
}
第二轮: 总时间LS:868477 总时间RLS:604649
第3次运行: 总时间LS:648266 总时间RLS:765009
第4次运行: 总时间LS:877037 总时间RLS:619652
答案 0 :(得分:2)
您的实验中未提及大量细节。
首先,如果每次都生成随机数据集,则无法得出任何结论。如果您生成一次巨大的数据集并且始终将这些数据用于这些测试,那么最好。在此之前,我们不能排除线性搜索可能面临对抗性输入。请记住,O(f(n))符号只表示,“它的性能不会比这更差”(在线性搜索的情况下,线性函数)。它没有声明任何关于多次运行的性能一致性。 (见脚注。)
接下来,运行总计是什么意思?你是否添加了每次搜索的执行时间?这不是衡量统计数据的好方法。最好是绘制单独的时间并检查运行时间分布的差异。
(附录:我认为每个进行基准测试的程序员都应该阅读this post by Zed Shaw。Shaw建议采用标准偏差的另一种方法是查看百分位数。就像标准偏差一样,它可以让你排除可能的异常值可能会扭曲你的总数。)
脚注:多次运行的效果分析属于摊销分析。然而,与更常见的渐近分析(确定单个运行的性能)不同,它不适用于所有算法。摊销算法和数据结构通常执行额外的内务管理任务,以“摊销”其他业务的绩效成本。
答案 1 :(得分:1)
完全取决于要搜索的key
考虑您拥有此数据1 2 3 4 5 6 7 8 9
使用线性serch搜索2
将比反向线性搜索花费更少的时间
使用反向线性搜索搜索8
所需的时间比线性搜索更短
如果你搜索5
,那么两者都会给你同样的时间
答案 2 :(得分:1)
如果生成一个新数组,然后运行LS,然后运行RLS,然后生成一个新数组并重复,这取决于计算机上的高速缓存大小,您可能会遇到数组不在LS缓存中的影响在RLS的缓存中。要验证缓存是否影响您的测试结果,您可能先运行RLS,然后运行LS(LS现在可以更快)。
答案 3 :(得分:1)
这完全取决于您的计算机体系结构和操作系统。但是,可以进行概述。
CPU一次运行大量进程,CPU只能执行命令。大多数基本操作都是CPU内的ALU操作。
将处理的数据存储在计算机内存中,在我们的案例中为RAM和CPU caches。 CPU通过缓存数据运行得更快。如果数据不在缓存中,则从内存中获取(ram)。 ram是一个内存,其地址的数据有random access时间。
缓存中可能没有数据
无法保证可以在缓存中找到要处理的数据。它完全依赖于在CPU上运行的其他进程。这是我们的一个障碍。在线性搜索期间CPU何时以及多少次未达到缓存数据。
无法保证线性搜索将以先发制人的方式完成
进程不在单个操作中运行。 CPU决定进程运行的次数,然后切换到其他进程。它被称为Context Swithcig。此外,在执行进程期间,CPU中存在许多synchronization个问题。
上图显示了CPU内部的进程生命周期。因此,无法保证在CPU中运行时的线性搜索。
您显示问题的结果显示运行时间是可变的,因为我解释。最好在内存和时序分析中比较算法的BigO值。
另见
答案 4 :(得分:0)
我的猜测,它与编译器以及它们如何实现这些数组有关。地址空间中放置这些数组索引的位置,访问方式等等......
再次猜测我无法确定这一点。另一点值得注意的是,虽然记录的时间一直较高,但它们从未高出一个数量级。在学术计算机科学家的运行时观点中,这些都是在O(n)中完成的,那些时间反映了这一点。