二分查找与暴力查找。

如果可能,我们的测试用例都会通过模拟实际情况来展示当前算法的必要性。这里该过程被称为白名单过滤。具体来说,可以想象一家信用卡公司,它需要检查客户的交易账号是否有效。为此,它需要:

  • 将客户的账号保存在一个文件中,我们称它为白名单;
  • 从标准输入中得到每笔交易的账号;
  • 使用这个测试用例在标准输出中打印所有与任何客户无关的账号,公司很可能拒绝此类交易。

在一家有上百万客户的大公司中,需要处理数百万甚至更多的交易都是很正常的。为了模拟这种情况,我们提供了文件largeW.txt(100万条:约6.7M)和largeT.txt(1000万条:约86M)。其中largeW.txt表示白名单,largeT.txt表示目标文件

给出暴力查找法(顺序查找)编写一个程序BruteForceSearch,在你的计算机上比较它和BinarySearch处理largeW.txt(100万条:约6.7M)和largeT.txt(1000万条:约86M)所需的时间。

说明:

算法第四版中提及的暴力查找法实为顺序查找法,详见代码:



1     public static int rank(int key, int[] a) {
2         for (int i = 0; i < a.length; i++) {
3             if (a[i] == key) return i;
4         }
5         return -1;
6     }



性能:

一个程序只是可用往往是不够的。例如,上面rank()的实现也可以很简单,它会检查数组的每个元素,甚至都不需要数组是有序的。

有了这个简单易懂的解决方案,我们为什么还需要归并排序和二分查找呢?计算机用rank()方法的暴力实现处理大量输入(比如含有100万个条目的白名单和1000万条交易)非常慢。没有如二分查找或者归并排序这样的高效算法,解决大规模的白名单问题是不可能得。良好的性能常常是极为重要的。

二分查找算法代码:



1    public static int rank(int key, int[] a) {
 2         int lo = 0;
 3         int hi = a.length - 1;
 4         while (lo <= hi) {
 5             // Key is in a[lo..hi] or not present.
 6             int mid = lo + (hi - lo) / 2;
 7             if      (key < a[mid]) hi = mid - 1;
 8             else if (key > a[mid]) lo = mid + 1;
 9             else return mid;
10         }
11         return -1;
12     }



实验代码:

 



1 package com.beyond.algs4.experiment;
 2 
 3 import java.io.File;  4 import java.util.Arrays;  5  6 import com.beyond.algs4.lib.BinarySearch;  7 import com.beyond.algs4.lib.StdIn;  8 import com.beyond.algs4.lib.StdOut;  9 import com.beyond.algs4.std.In; 10 11 public class PerfBruteForceSearch { 12 13 /** 14  * @param args 15 */ 16 public static void main(String[] args) { 17 String whitelist = StdIn.readString(); 18 int[] whitelistArray = readlist(whitelist); 19 String targetlist = StdIn.readString(); 20 int[] targetlistArray = readlist(targetlist); 21 22 long t1 = System.currentTimeMillis(); 23 // for (int i = 0; i < targetlistArray.length; i++) { 24 // BruteForceSearch.rank(targetlistArray[i], whitelistArray); 25 // } 26 // StdOut.println(String.format("BruteForceSearch in %d milliseconds", (long) (System.currentTimeMillis() - t1))); 27 // 28 // t1 = System.currentTimeMillis(); 29  Arrays.sort(whitelistArray); 30 for (int i = 0; i < targetlistArray.length; i++) { 31  BinarySearch.rank(targetlistArray[i], whitelistArray); 32  } 33 StdOut.println(String.format("BinarySearch in %d milliseconds", (long) (System.currentTimeMillis() - t1))); 34  } 35 36 private static int[] readlist(String whitelist) { 37 File fWhitelist = new File(whitelist); 38 In in = new In(fWhitelist); 39 int[] whitelistArray = in.readAllInts(); 40 return whitelistArray; 41  } 42 43 }



实验结果:

1)tinyW.txt 与 tinyT.txt



./TinyW.txt
./TinyT.txt
BruteForceSearch in 0 milliseconds
BinarySearch in 1 milliseconds



2)largeW.txt 与 largeT.txt(BruteForceSearch in hours)



./largeW.txt
./largeT.txt
BinarySearch in 2399 milliseconds



补充说明:

实验方法忽略读取测试数据文件对算法的影响

实验方法忽略BruteForceSearch与BinarySearch执行的影响

注意

在内存不够时,可能出现错误:Java heap space



1 ./largeW.txt
 2 ./largeT.txt
 3 Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
 4     at java.nio.HeapCharBuffer.<init>(Unknown Source)
 5     at java.nio.CharBuffer.allocate(Unknown Source)
 6     at java.util.Scanner.makeSpace(Unknown Source)
 7     at java.util.Scanner.readInput(Unknown Source)
 8     at java.util.Scanner.next(Unknown Source)
 9     at com.beyond.algs4.std.In.readAll(In.java:247)
10     at com.beyond.algs4.std.In.readAllStrings(In.java:322)
11     at com.beyond.algs4.std.In.readAllInts(In.java:348)
12     at com.beyond.algs4.experiment.PerfBruteForceSearch.readlist(PerfBruteForceSearch.java:39)
13     at com.beyond.algs4.experiment.PerfBruteForceSearch.main(PerfBruteForceSearch.java:20)



在更改win32_x86版本eclipse 并把eclipse.ini更新为-Xmx2048m超过1024时,eclipse会出错“Failed to create the Java Virtual Machine”。建议更换64位版本。

计算机基本配置

处理器: Inter(R) Pentium(R) CPU G3220 @3.00GHz

内存:8.00GB

系统类型:64位操作系统

软件环境

IDE: Version: Mars Release (4.5.0)

JVM:



1 -startup
 2 plugins/org.eclipse.equinox.launcher_1.3.100.v20150511-1540.jar
 3 --launcher.library
 4 plugins/org.eclipse.equinox.launcher.win32.win32.x86_64_1.1.300.v20150602-1417
 5 -product
 6 org.eclipse.epp.package.jee.product
 7 --launcher.defaultAction
 8 openFile
 9 --launcher.XXMaxPermSize
10 256M
11 -showsplash
12 org.eclipse.platform
13 --launcher.XXMaxPermSize
14 256m
15 --launcher.defaultAction
16 openFile
17 --launcher.appendVmargs
18 -vmargs
19 -Dosgi.requiredJavaVersion=1.7
20 -Xms512m
21 -Xmx2048m



 

参考资料:

算法 第四版  谢路云 译 Algorithms Fourth Edition [美] Robert Sedgewick, Kevin Wayne著

http://algs4.cs.princeton.edu/home/

源码下载链接:

http://pan.baidu.com/s/1eQjMd0Y