• 【算法】二分查找与暴力查找(白名单过滤)


     二分查找与暴力查找。

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

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

    在一家有上百万客户的大公司中,需要处理数百万甚至更多的交易都是很正常的。为了模拟这种情况,我们提供了文件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

  • 相关阅读:
    概率论——随机事件及其概率
    Web应用程序项目以配置使用IIS。未找到Web服务器”链接地址”
    LaTeX中.sty文件缺失解决办法
    IIS中的经典模式和集成模式有什么区别
    判断有序整型数组中是否存在两数,相加之和等于给定的任意整数
    51Job的搜索技巧
    登录失败。该登录名来自不受信任的域,不能与 Windows 身份验证一起使用。
    Ubuntu使用Latex模板moderncv写简历
    COM相关操作(C#)
    什么是单线程单元(STA)什么是多线程单元(MTA)
  • 原文地址:https://www.cnblogs.com/richaaaard/p/4616518.html
Copyright © 2020-2023  润新知