• 用二进制的与、或、非运算方便的解决实际问题


     转载 http://qihigh-hotmail-com.iteye.com/blog/1329696

    二进制的与、或、非运算特殊用法的不同运用场合:

    1.权限控制 
        下面我用几个数字来代表增,删,改,查。(注:1带有有权限,有几个1,就代表有几个权限,1的位置不同,所带表的权限也不同) 
    Java代码  收藏代码
    1. 1---------增--------(转二进制)-----(0001)  
    2. 2---------删----------------------(0010)  
    3. 4--------改----------------------(0100)  
    4. 8--------查----------------------(1000)  


    管理员拥有所有的权限,所以,控制管理员的权限的数字为(15),转化二进制的格式为:(1111)。算法为:“1|2|4|8“ 
    撤销管理员的删权限(2),控制管理员的权限的数字为(13),转化二进制的格式为:(1101)。算法为:”15 & (~2)” 
    判断管理员的权限中是否有某个权限。如在控制管理员的权限的数字为(13)时,判断管理员是否具有修改的权限(4)。算法为:“13 & 4==0”,假如等于0的话,表示,权限不存在,假如不等于0的话,表示,此权限已经存在。
     

    2.分类组合 
       假如一个类要支持很多操作,操作和操作之间可能没有联系,可能有相反关系无法共存,可能有特殊关系必须共存,这种要分很多类还要处理联系的情况下可以考虑采用二进制来解决。 
        我这里的例子是java做的文件搜索,用的是递归,搜索的时候可以搜索文件、文件夹,搜索的方式可以有正则表达式匹配、以特定开始、以特定结束、以是否包含的方式。而且除了正则则要单独处理,其他方式直接可以进行组合。 
        通过二进制分类
     
    Java代码  收藏代码
    1. /** 查找文件夹 */  
    2. public static final int      FIND_DIRECTORY  = 1;  
    3. /** 查找文件 */  
    4. public static final int      FIND_FILE       = 2;  
    5. /** 正则查找 */  
    6. public static final int      FIND_BY_REGEX   = 4;  
    7. /** 起始于 */  
    8. public static final int      FIND_START_WITH = 8;  
    9. /** 结束于 */  
    10. public static final int      FIND_END_WITH   = 16;  
    11. /** 包含于 */  
    12. public static final int      FIND_CONTAIN    = 32;  
    13. // rule  
    14. private int           _rule        = 0;  

        当程序传入规则之后,我可以很方便的加入到 _rule中 
    Java代码  收藏代码
    1. /** 添加规则 */  
    2. public int ruleAdd(int r) {  
    3.   
    4.   _rule = _rule | r;  
    5.   return _rule;  
    6. }  

         去除 和 判断是否有这个规则 

    Java代码  收藏代码
    1. /** 去除规则 */  
    2. public int ruleRemove(int r) {  
    3.   
    4.   _rule = _rule & (~r);  
    5.   return _rule;  
    6. }  
    7.   
    8. /** 是否包含规则 */  
    9. public Boolean hasRule(int r) {  
    10.   
    11.   return (_rule & r) != 0;  
    12. }  

        之后处理时进行 if分类 就可以很方便 
    Java代码  收藏代码
    1. /** 
    2.     * 判断是否满足规则用户指定的rule (正则表达式 ______ 开始于 __________ 结束于) 
    3.     * 
    4.     * @param content 
    5.     * @return 
    6.     */  
    7.    public Boolean meetRule(File pathname) {  
    8.   
    9.      Boolean result = true;  
    10.      // 查找路径  
    11.      if (hasRule(FIND_DIRECTORY)) {  
    12.          result = result && pathname.isDirectory();  
    13.      }  
    14.      // 查找文件  
    15.      if (hasRule(FIND_FILE)) {  
    16.          result = result && pathname.isFile();  
    17.      }  
    18.      String fileName = pathname.getName().toUpperCase();  
    19.      // 按照开始于查找  
    20.      if (hasRule(FIND_START_WITH)) {  
    21.          result = result && fileName.startsWith(_fix.get(FIND_START_WITH).toUpperCase());  
    22.      }  
    23.      // 按照结束于查找  
    24.      if (hasRule(FIND_END_WITH)) {  
    25.          result = result && fileName.endsWith(_fix.get(FIND_END_WITH).toUpperCase());  
    26.      }  
    27.      // 文件名包含查找  
    28.      if (hasRule(FIND_CONTAIN)) {  
    29.          result = result && fileName.contains(_fix.get(FIND_CONTAIN).toUpperCase());  
    30.      }  
    31.      // 按照正则查找 不区分大小写  
    32.      if (_rule == FIND_BY_REGEX) {  
    33.          result = result && Pattern.compile(_fix.get(FIND_BY_REGEX), Pattern.CASE_INSENSITIVE).matcher(fileName).find();  
    34.      }  
    35.      return result;  
    36.    }  


    大体就是这个个意思,完整代码 
    Java代码  收藏代码
    1. /** 
    2.  * 查找指定路径下 满足条件的文件、文件夹(不区分大小写) 
    3.  * 
    4.  * @see 
    5.  * @author kaven 
    6.  * @version 1.0, 2011-8-27 
    7.  * @since 1.0, 2011-8-27 
    8.  */  
    9. public class PathSearch {  
    10.   
    11.     /** 查找文件夹 */  
    12.     public static final int      FIND_DIRECTORY  = 1;  
    13.     /** 查找文件 */  
    14.     public static final int      FIND_FILE       = 2;  
    15.     /** 正则查找 */  
    16.     public static final int      FIND_BY_REGEX   = 4;  
    17.     /** 起始于 */  
    18.     public static final int      FIND_START_WITH = 8;  
    19.     /** 结束于 */  
    20.     public static final int      FIND_END_WITH   = 16;  
    21.     /** 包含于 */  
    22.     public static final int      FIND_CONTAIN    = 32;  
    23.   
    24.     // rule  
    25.     private int           _rule        = 0;  
    26.     // 用户输入的用来匹配文件名的字段 或者正则  
    27.     private Map<Integer, String> _fix         = new HashMap<Integer, String>();  
    28.     // 文件  
    29.     private List<File>     _files = new ArrayList<File>();  
    30.   
    31.     public PathSearch() {  
    32.   
    33.     }  
    34.   
    35.     // public PathSearch(Map<Integer, String> aFix) {  
    36.     //  
    37.     // this._fix = aFix;  
    38.     // }  
    39.   
    40.     /** 添加规则 */  
    41.     public int ruleAdd(int r) {  
    42.   
    43.       _rule = _rule | r;  
    44.       return _rule;  
    45.     }  
    46.   
    47.     /** 去除规则 */  
    48.     public int ruleRemove(int r) {  
    49.   
    50.       _rule = _rule & (~r);  
    51.       return _rule;  
    52.     }  
    53.   
    54.     /** 是否包含规则 */  
    55.     public Boolean hasRule(int r) {  
    56.   
    57.       return (_rule & r) != 0;  
    58.     }  
    59.   
    60.     /** 
    61.      * 判断是否满足规则用户指定的rule (正则表达式 ______ 开始于 __________ 结束于) 
    62.      * 
    63.      * @param content 
    64.      * @return 
    65.      */  
    66.     public Boolean meetRule(File pathname) {  
    67.   
    68.       Boolean result = true;  
    69.       // 查找路径  
    70.       if (hasRule(FIND_DIRECTORY)) {  
    71.           result = result && pathname.isDirectory();  
    72.       }  
    73.       // 查找文件  
    74.       if (hasRule(FIND_FILE)) {  
    75.           result = result && pathname.isFile();  
    76.       }  
    77.       String fileName = pathname.getName().toUpperCase();  
    78.       // 按照开始于查找  
    79.       if (hasRule(FIND_START_WITH)) {  
    80.           result = result && fileName.startsWith(_fix.get(FIND_START_WITH).toUpperCase());  
    81.       }  
    82.       // 按照结束于查找  
    83.       if (hasRule(FIND_END_WITH)) {  
    84.           result = result && fileName.endsWith(_fix.get(FIND_END_WITH).toUpperCase());  
    85.       }  
    86.       // 文件名包含查找  
    87.       if (hasRule(FIND_CONTAIN)) {  
    88.           result = result && fileName.contains(_fix.get(FIND_CONTAIN).toUpperCase());  
    89.       }  
    90.       // 按照正则查找 不区分大小写  
    91.       if (_rule == FIND_BY_REGEX) {  
    92.           result = result && Pattern.compile(_fix.get(FIND_BY_REGEX), Pattern.CASE_INSENSITIVE).matcher(fileName).find();  
    93.       }  
    94.       return result;  
    95.     }  
    96.   
    97.     /** 
    98.      * 添加规则(等价于 ruleAdd) 
    99.      * 
    100.      * @param rule 
    101.      */  
    102.     public void addRule(int rule) {  
    103.   
    104.       ruleAdd(rule);  
    105.     }  
    106.   
    107.     /** 
    108.      * 添加规则 和 规则验证字段 
    109.      * 
    110.      * @param rule 
    111.      * @param value 
    112.      */  
    113.     public void addRule(int rule, String value) {  
    114.   
    115.       ruleAdd(rule);  
    116.       this._fix.put(rule, value);  
    117.     }  
    118.   
    119.     /** 
    120.      * 根据给定的path 查找其下满足特定条件的文件、文件夹 
    121.      */  
    122.     public void findUnderPath(String path) {  
    123.   
    124.       File directory = new File(path);  
    125.       if (!directory.exists()) {  
    126.           // 路径不存在  
    127.           return;  
    128.       }  
    129.       File[] files = directory.listFiles(new FileFilter() {  
    130.   
    131.           @Override  
    132.           public boolean accept(File pathname) {  
    133.   
    134.             return meetRule(pathname);  
    135.           }  
    136.       });  
    137.       _files = Arrays.asList(files);  
    138.     }  
    139.   
    140.     /** 
    141.      * 根据指定的path 查找其下包括子文件夹 所有满足特定条件的文件、文件夹 
    142.      * 
    143.      * @return 
    144.      */  
    145.     public void findDeepUnderPath(File pathName) {  
    146.   
    147.       if (!pathName.exists()) {  
    148.           return;  
    149.       }  
    150.       // 获取所有 符合规则的文件 列表  
    151.       File[] files = pathName.listFiles(new FileFilter() {  
    152.   
    153.           @Override  
    154.           public boolean accept(File pathname) {  
    155.   
    156.             return meetRule(pathname);  
    157.           }  
    158.       });  
    159.       // 添加到结果集列表中  
    160.       _files.addAll(Arrays.asList(files));  
    161.       // 查找所有目录  
    162.       File[] directories = pathName.listFiles(new FileFilter() {  
    163.   
    164.           @Override  
    165.           public boolean accept(File pathname) {  
    166.   
    167.             return pathname.isDirectory();  
    168.           }  
    169.       });  
    170.       // 获取子文件夹下的文件  
    171.       for (File directory : directories) {  
    172.           findDeepUnderPath(directory);  
    173.       }  
    174.     }  
    175.   
    176.     public List<File> getFiles() {  
    177.   
    178.       return _files;  
    179.     }  
    180.   
    181.     @Test  
    182.     public void testFind() {  
    183.   
    184.       String path = "F:\\work_tools";  
    185.       PathSearch ps = new PathSearch();  
    186.   
    187.       // ps.addRule(FIND_FILE);  
    188.       ps.addRule(FIND_BY_REGEX, "[\\d]");  
    189. //     ps.addRule(FIND_END_WITH, "rar");  
    190.   
    191.       // ps.findUnderPath(path);  
    192.       ps.findDeepUnderPath(new File(path));  
    193.       List<File> files = ps.getFiles();  
    194.       for (File f : files) {  
    195.           System.out.println(f.getPath());  
    196.       }  
    197.     }  
    198.   
    199. //    @Test  
    200.     public void testRule() {  
    201.   
    202.       System.out.println(ruleAdd(1));  
    203.       System.out.println(ruleAdd(4));  
    204.       System.out.println(ruleAdd(8));  
    205.       System.out.println(hasRule(4));  
    206.       System.out.println(ruleRemove(4));  
    207.       System.out.println(hasRule(4));  
    208.     }  
    209. }  

    3.快速找出两个list(或数组)中不同的对象 
        一般的想法都是通过对两个list进行 循环嵌套,每找到一个,remove一个,这样的话有两个缺点:一个是速度,在最差的情况下是O(n^2),这对于数量大的是比较慢的。二是由于要remove元素,不能采用iterator尽心循环(据说采用迭代器java会有缓存优化)。 
          这个就可以采用二进制来解决,其实这里用二进制只是一种方式,完全可以用 权的概念,一个权设为10,一个权设为1
    任意两个不相等的数都可以,如果多个list和数组的话,还是二进制方式比较清楚)。假如数组种的对象通过code来进行标示,新建一个 
    Java代码  收藏代码
    1. Map<String,Integer> countMap = new HashMap<String,Integer>()//key -- > code, value -- > 权  

    分别对两个list进行第一次循环 
       循环list1的时候:
     
    Java代码  收藏代码
    1. countMap.put(code,10);  

        循环list2的时候: 

    Java代码  收藏代码
    1. if(null == countMap.get(code)){  
    2.    countMap.put(code, 0);//初始化为0  
    3. }  
    4. int count = countMap.get(code);//获取当前权  
    5. countMap.put(code, count + 1);//更新权  


    这样一来,所有list1独有的,countMap表现为Value为1,list2独有的,countMap表现为Value为10,共有的表现为Value为11 
    然后进行第二次循环,将list1、list2根据code进行分类,组合成两个HashMap,以方便根据code找出code相同的部分(code相同不代表其他属性也相同,实际处理中可能会有用,不管你用没用到,反正我用到了)和code不同的部分。 

    之后就是 根据找出来的code,各自的map中获取对应的对象了。 
    复制度O(2n) 
    我能想到的是这个方法,不知道有没有更好的,望提示!!! 
    上代码:
     
    Java代码  收藏代码
    1. /** 
    2.  * 通过3次循环,对field 进行快速分类,找出彼此code不同的TableField 
    3.  * @author qihuan 
    4.  * 
    5.  */  
    6. public class QuickDiff {  
    7.     private List<TableField> oldFieldPop = new ArrayList<TableField>();  
    8.     private List<TableField> newFieldAppend = new ArrayList<TableField>();  
    9.     private List<String> commonCode = new ArrayList<String>();  
    10.     private Map<String, TableField> newFieldMap;  
    11.     private Map<String, TableField> oldFieldMap;  
    12.       
    13.     public QuickDiff(){  
    14.     }  
    15.     /** 
    16.      * 通过3次循环,对field 进行快速分类 
    17.      * @param oldFields 
    18.      * @param newFields 
    19.      */  
    20.     public void doDiff(List<TableField> oldFields,List<TableField> newFields){  
    21.     // key:desc -- value:对应出现次数  
    22.     Map<String,Integer> countMap = new HashMap<String, Integer>();  
    23.     addToMap(countMap,oldFields,1);//old 权为 1  
    24.     addToMap(countMap,newFields,10);//new 权为10  
    25.       
    26.     newFieldMap = turnToMapByCode(newFields);  
    27.     oldFieldMap = turnToMapByCode(oldFields);  
    28.     //对 独有的code进行分类  
    29.     for(String code : countMap.keySet()){  
    30.         int value = countMap.get(code);  
    31.         if(value == 11){  
    32.         commonCode.add(code);  
    33.         //do nothing  
    34.         }else if(value == 10){  
    35.         newFieldAppend.add(newFieldMap.get(code));  
    36.         }else if(value == 1){  
    37.         oldFieldPop.add(oldFieldMap.get(code));  
    38.         }  
    39.     }  
    40.     }  
    41.       
    42.     /** 
    43.      * 按照 code 进行分类 
    44.      * @param fields 
    45.      * @return 
    46.      */  
    47.     private Map<String, TableField> turnToMapByCode(List<TableField> fields){  
    48.     Map<String, TableField> fieldMap = new HashMap<String, TableField>();  
    49.     for(TableField tf : fields){  
    50.         String code = tf.getCode();  
    51.         fieldMap.put(code, tf);  
    52.     }  
    53.     return fieldMap;  
    54.     }  
    55.     /** 
    56.      *  
    57.      * @param countMap 计数map 
    58.      * @param fields  
    59.      * @param value 权 
    60.      */  
    61.     private void addToMap(Map<String, Integer> countMap, List<TableField> fields, int value) {  
    62.     for(TableField tf : fields){  
    63.         String code = tf.getCode();  
    64.         if(null == countMap.get(code)){  
    65.         countMap.put(code, 0);  
    66.         }  
    67.         int count = countMap.get(code);//获取当前权  
    68.         countMap.put(code, count + value);//更新权  
    69.     }  
    70.     }  
    71.     /** 
    72.      * old 独有的 
    73.      * @return 
    74.      */  
    75.     public List<TableField> getOldFieldPop() {  
    76.       
    77.         return oldFieldPop;  
    78.     }  
    79.     /** 
    80.      * new 独有的 
    81.      * @return 
    82.      */  
    83.     public List<TableField> getNewFieldAppend() {  
    84.       
    85.         return newFieldAppend;  
    86.     }  
    87.     /** 
    88.      * 共有的 
    89.      * @return 
    90.      */  
    91.     public List<String> getCommonCode() {  
    92.       
    93.         return commonCode;  
    94.     }  
    95.     /** 
    96.      * newField to Map 
    97.      * @return 
    98.      */  
    99.     public Map<String, TableField> getNewFieldMap() {  
    100.       
    101.         return newFieldMap;  
    102.     }  
    103.     /** 
    104.      * oldField to Map 
    105.      * @return 
    106.      */  
    107.     public Map<String, TableField> getOldFieldMap() {  
    108.       
    109.         return oldFieldMap;  
    110.     }  
    111.       
    112. }  
  • 相关阅读:
    poj 1961 Period
    call 大佬 help7——kmp 补齐 循环节
    hdu 3746 Cyclic Nacklace
    poj 2406 Power Strings
    [Baltic2009]Radio Transmission
    poj 2752 Seek the Name, Seek the Fame
    hdu 3336 Count the string
    hdu 2594 Simpsons’ Hidden Talents
    hdu 1711 Number Sequence
    我在开发第一个Swift App过程中学到的四件事
  • 原文地址:https://www.cnblogs.com/chenying99/p/2634383.html
Copyright © 2020-2023  润新知