• 集合包含关系的快速算法 simcity 博客园


    集合包含关系的快速算法 - simcity - 博客园

        集合包含关系的快速算法
        2012-10-05 22:18 by simcity, 751 阅读, 0 评论, 收藏, 编辑

        #1 每行数据代表一个集合,如何判断集合的包含关系? -- 集合的数据仅在有限范围内。

        0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23       a --24个元素
        1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24     b --24个元素

        最容易想到的是蛮力运算,计算前还应该知道谁元素多,对吧?不过还好,我耍了个花招,在读取数据时已经把数组元素数目存入数组第0号元素。
        1 for each element x in a
        2     if (!setContain(b , x))
        3        return false;
        4
        5 return true;   

        #2 数据在31以内,考虑用无符号数编码数组
        例如 1 2 3 4 用 0x00000000 00000000 00000000 00001111编码,也就是1用第一个bit,2用第二个bit,依此类推...
        但是数据里面有0,也好说,0用第一个bit,1用第二个bit,依此类推...
        这样1 2 3 4 最终形式 0x00000000 00000000 00000000 00011110
        这么一来要判断要简单多了,只需要
        复制代码
        1 unsigned src //代表较多元素数组的编码
        2 unsigned dst //代表较少元素数组的编码
        3 if (src & dst == dst)
        4     return true;
        5
        6 return false;
        复制代码

        但是且慢,如何将1 2 3 4等元素存入 src 之类变量?
        So, 手工加工的 table登场
        复制代码
         1     unsigned int table[32] = {
         2         0x00000001, 0x00000002, 0x00000004, 0x00000008,
         3         0x00000010, 0x00000020, 0x00000040, 0x00000080,
         4         0x00000100, 0x00000200, 0x00000400, 0x00000800,
         5         0x00001000, 0x00002000, 0x00004000, 0x00008000,
         6         0x00010000, 0x00020000, 0x00040000, 0x00080000,
         7         0x00100000, 0x00200000, 0x00400000, 0x00800000,
         8         0x01000000, 0x02000000, 0x04000000, 0x08000000,
         9         0x10000000, 0x20000000, 0x40000000, 0x80000000
        10     };
        复制代码

        只需要每数组扫描一遍即可实现目标。
        1 src = 0;
        2
        3 for each element x in a
        4     src = src + table[x];

        问题基本解决。

        #3 考虑如下数组:如何扩展至64位

        25 26 27 28 29 30 31 32 33 34 35 36 37 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
        26 27 28 29 30 31 32 33 34 35 36 37 38 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

        可按下图来考虑
        复制代码
        number      bit
        0           1
        .           .
        .           .
        .           .
        31          32


        32 -- 0     1
        .           .
        .           .
        .           .
        63 -- 31    32
        复制代码

        再构造数组
        1 int cache = {0, 32};
        2 unsigned int cacheManager[2][2];
        3 //用二维数组维护两个数组的编码,每行编码一数组

        方法如下,分别以16  , 63为例

        运算 (16 & 0x00000020) >> 5 得出  0,  然后 16 - cache[0] 得出 16,   16 存入cacheManager[?][ 0 ]

        运算 (63 & 0x00000020) >> 5 得出  1,  然后 63 - cache[1] 得出 31,    31存入cacheManager[?][ 1 ]

        #4 实际代码,利用此方法,程序运行时间缩短到原来1/3.
        复制代码
         1 int fillCacheManager(normalInt * index, Element (* dt)[ElementNumber], unsigned int (*cm)[cacheLine], unsigned int * table){
         2     int element;
         3     int cache[2] = {0 , 32};
         4     int serial;
         5
         6     for( normalInt m=1; m<=index[0]; m++ ){
         7         normalInt t = index[m];
         8         cm[t][0] = 0;
         9         cm[t][1] = 0;
        10         for ( normalInt n=1; n<=dt[t][0]; n++  ){
        11             element = dt[t][n];
        12             serial = (element & 0x00000020) >>5;
        13             element = element - cache[serial];
        14             cm[t][serial] = cm[t][serial] + table[element] ;
        15         }
        16     }
        17
        18     return 0;
        19 }
        20
        21
        22 int quickTableReducton(normalInt * index, Element (* dt)[ElementNumber], unsigned int (*cm)[cacheLine]){
        23     normalInt subset = index[0];
        24     if (subset == 0) return -1;
        25    
        26     for (normalInt m=1; m<subset; m++ ){
        27         if (index[m] < 0) continue;
        28        
        29         for(normalInt n=m+1; n<subset+1; n++){
        30             if(index[n] < 0) continue;
        31             if(n == m) continue;
        32
        33             normalInt src = index[m];
        34             normalInt dst = index[n];
        35             normalInt QQ = dst;
        36             bool swaped = false;
        37             if (dt[src][0] < dt[dst][0]){
        38                 swaped = true;
        39                 QQ = src;
        40             }
        41
        42             if (  (cm[src][0] & cm[dst][0]) == cm[QQ][0]    &&   (cm[src][1] & cm[dst][1]) == cm[QQ][1]  ){
        43                 int t = m;
        44                 if (swaped) t = n;
        45                 index[t] = -2;
        46                 index[0] = index[0]-1;
        47                 if (swaped == false) break;           
        48             }
        49         }
        50     }
        51
        52     normalInt idx[indexCount];//indexOver
        53     normalInt len=1;
        54     for (normalInt m=1; index[m]!=indexOver; m++)//m<=index[0]
        55         if (index[m] > -1){
        56             idx[len] = index[m];
        57             len++;
        58         }
        59
        60     for (normalInt m=1; m<len; m++) index[m] = idx[m];
        61     index[len] = indexOver;
        62
        63     return 0;
        64 }
        复制代码

        #5 STL bitset : better choice?
        分类: C/C++

  • 相关阅读:
    MySQL之存储引擎
    MySQL之触发器
    MySQL之存储过程
    MySQL之自定义函数
    MySQL之视图
    三种方式安装mariadb-10.3.18
    Linux创建智能DNS
    CentOS 7 搭建Cobbler实现自动化安装系统
    搭建PXE实现自动化安装系统
    编译安装dropbear
  • 原文地址:https://www.cnblogs.com/lexus/p/2714695.html
Copyright © 2020-2023  润新知