【问题标题】:Find all possible subsets of a short array in C在 C 中查找短数组的所有可能子集
【发布时间】:2013-12-17 12:54:00
【问题描述】:

我在 C 语言中有一个相对较短的数组(= 2 的所有可能子集。通过递归构建所有子列表的列表,有很多方法可以做到这一点,但我想避免这增加的额外开销。我只需要遍历每个子集;我不需要跟踪它们。

这听起来像是一个奇怪的要求,但原因是我还希望能够在每个工作项内存非常昂贵的 OpenCL 内核中使用它。我真的很想避免分配列表​​列表。

【问题讨论】:

    标签: c arrays opencl bit-manipulation subset


    【解决方案1】:

    如果您包含大小为 0 和 1 的子集并过滤掉它们(这很简单,
    if ((set & (set - 1)) == 0),忽略它),您实际上只是从 0 迭代到 1 << n

    这比 Gosper's Hack 简单得多,这很酷,但由于您基本上需要所有子集长度,因此使用它没有什么意义。只有几个子集以这种方式被跳过,因为您不想要的唯一重要组只有大小 n

    【讨论】:

      【解决方案2】:

      鉴于数组非常短,我们可以在 32 位无符号整数上使用一些位摆弄来完成此操作。如果数组的每个元素都表示为位串中的单个位,并且该位的值指定该元素是否在当前子集中,则问题简化为查找所有具有特定长度的位串,其中没有位设置超过kth 位位置,其中k 是数组的长度。

      /*
      Given:
      max = longest subset length
      min = shortest subset length
      num = number of elements in array
      */
      
      unsigned int i, n, v, w;
      
      // Loop across subset lengths
      for (n = max; n >= min; n--) {
      
          // Generate lexiographically first subset (n rightmost bits set)
          v = (~0U)>>(sizeof(unsigned int)*8-n);
      
          // Stop once a bit is set that is outside our array
          while (v < (1U<<num)) {
              // Look for elements whose corrensponding bit is set
              for (i = 0; i < num; i++) {
                  if (v & (1U<<i)) {
                      // array[i] is in current subset
                  }
              }
      
              // Move to lexiographically next bit string with n bits set
              // http://www-graphics.stanford.edu/~seander/bithacks.html#NextBitPermutation
              // Could switch to __builtin_ctz() version for speed
              w = (v | (v - 1)) + 1;
              w |= ((((w & -w) / (v & -v)) >> 1) - 1);
              v = w;
          }
      }
      

      【讨论】:

        【解决方案3】:

        您需要的是一种算法,该算法可以在给定工作项 ID 和数组长度的情况下为您提供排列或组合序列。示例:

        Array: 1 2 3
        Permutations: 
        1 2 3 
        1 3 2 
        2 1 3
        2 3 1
        3 1 2
        3 2 1
        
        workitem i=5 -> N=3, K=6; *Some algorithm that gives 312*
        

        我可以猜到这些算法存在,你甚至可以编写自己的应用逻辑。 (我稍后会尝试将它们挖掘出来,但搜索“并行排列/组合”)

        然后,您只需要编写一个通用内核来运行算法,全局大小的数量等于可能的组合数量。我会为数组值使用常量内存(因为它很小)。 对于所有输出值,您还需要一个 BIG 输出大小。

        【讨论】:

          猜你喜欢
          • 2011-08-10
          • 1970-01-01
          • 1970-01-01
          • 2013-12-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多