例1:
ThreeSum:统计一个文件中所有和为0的三整数元组的数量(假设整数不会溢出)。
处理数据:算法第四版网站中的1Mints.txt,其中是100万个随机生成的int值
public class TreeSum
{
public static int count (int [] a)
{ //统计和为0的元组的数量
int N = a.length;
int cnt = 0;
for(int i = 0;i < N; i++)
for(int j = i+1; j < N; j++)
for(int k = j+1; j <N ;k++)
if(a[i] + a[j] + a[k] == 0)
cnt++;
return cnt;
}
public static void main (String[] args)
{
int[] a = In.readInts(args[0])
stdOut.println(count(a));
}
}
计时器:验证关于程序的运行时间和问题规模
一种表示计时器的抽象数据类型,它的实现基于java 系统的currentTimeMillis()方法,该方法能返回以毫秒计数的当前时间。它在构造函数中保存了当前时间,并在elapsedTime()方法被调用时再次调用该方法来计算得到对象创建以来经过的时间。
API public class Stopwatch
Stopwatch() 创建一个计时器
double elapsedTime() 返回对象创建以来所经过的时间
典型用例
public static void main(String[] args)
{
int N = Integer.parseInt(args[0]);
int[] a = new int[N];
for(int i = 0; i < N;i++)
a[i] = StdRandom.uniform(-1000000,1000000);
Stopwatch timer = new Stopwatch();
int cnt = Three.count(a);
double time = timer.elapsedTime();
StdOut.println(cnt + “triples” + time +"seconds");
}
使用方法
% java Stopwatch 1000
51 triples 0.448 seconds
% java Stopwatch 2000
516 triples 3.855 seconds
数据类型的实现
public class Stopwatch
{
private final long start;
public Stopwatch();
{ start = System.currentTimeMillis(); }
public double elapsedTime()
{
long now = System.currentTimeMillis();
return(now - start)/1000;
}
}
作为问题规模的一个函数,我的程序运行时间是多少?
实验程序
public class DoublingTest
{
public static double timeTrial(int N)
{ //为处理N个随机的六位整数的ThreeSum.count()计时
int MAX = 1000000;
int[] a = new int[N];
for(int i = 0;i < N;i++)
a[i] = StdRandom.uniform(-MAX,MAX);
Stopwatch timer = new Stopwatch();
int cnt = ThreeSum,count(a);
return timer.elapsedTime();
}
public static void main(String[] args)
{
for(int N = 250;true;N += N)
{
double time = timeTrial(N);
StdOut.printf("%7d %5.1f\n",N,time);
}
}
}
实验结果
% java DoublingTest
250 0.0
500 0.0
1000 0.1
2000 0.8
4000 6.4
8000 51.1
...
将以上得到d数据绘制成图表。使用的分别是标准比例尺和对数比例尺。其中x轴表示N,y轴表示为程序的运行时间T(N)。
由数的图像可以得到一个关于运行时间的猜想——因为数据和斜率3的直线完全吻合,该直线公式为
lg(T(N)) = 3lgN + lga 此公示等价于 T(N) = aN3