代码之家  ›  专栏  ›  技术社区  ›  ravenspoint

迭代任何大小的子集

  •  3
  • ravenspoint  · 技术社区  · 16 年前

    我可以迭代大小为1的子集

    for( int a = 0; a < size; a++ ) {
    

    或大小为2的子集

    for( int a1 = 0; a1 < size; a1++ ) {
        for( int a2 = a1+1; a2 < size; a2++ ) {
    

    或3

    for( int a1 = 0; a1 < size; a1++ ) {
    for( int a2 = a1+1; a2 < size; a2++ ) {
       for( int a3 = a2+1; a3 < size; a3++ ) {
    

    但是如何对大小为n的子集执行此操作?

    根据亚当·罗森菲尔德的回答

    void iterate(int *a, int i, int size, int n)
    {
     int start = 0;
     if( i > 0 ) start = a[i-1]+1;
     for(a[i] = start; a[i] < n; a[i]++) {
      if(i == n-1) {
          // a is the array of indices of size n
          for( int k = 0; k < size; k++ ) {
              printf("%d ",a[k]);
          }
          printf("\n");
      }
            else
                iterate(a, i+1, size, n);
        }
    }
    
    5 回复  |  直到 16 年前
        1
  •  7
  •   Adam Rosenfield    16 年前

    您可以使用递归:

    void iterate(int *a, int i, int size, int n)
    {
        for(a[i] = 0; a[i] < size; a[i]++)
        {
            if(i == n-1)
                DoStuff(a, n);  // a is the array of indices of size n
            else
                iterate(a, i+1, size, n);
        }
    }
    ...
    // Equivalent to 4 nested for loops
    int a[4];
    iterate(a, 0, size, 4);
    
        2
  •  2
  •   Daniel A. White    16 年前

    您可能可以使用一些递归来完成这项工作。

        3
  •  1
  •   Adrian Park    16 年前

    这是我用来解决类似问题的东西。它不使用递归,而是使用索引向量。

    #include <vector>
    
    template<class T>
    class MultiForVar {
    std::vector<T> _begin, _end, _vars;
    inline int dim(){return _vars.size();}
    public:
    MultiForVar(std::vector<T> begin, std::vector<T> end) : _begin(begin), _end(end), _vars(_begin)
    {
      assert(begin.size() == end.size() and "Starting and ending vector<T> not the same size!" );
    }
    MultiForVar& operator ++()
    {
      ++_vars[dim()-1];
      for(int d = dim()-1; d > 0; --d)
      {
        if( _vars[d] >= _end[d] )
        {
          _vars[d] = _begin[d];
          ++_vars[d-1];
        }
      }
      return *this;
    }
    bool done()
    {
      /*for(int d = 0; d < dim(); ++d)
        if( _vars[d] < _end[d] )
          return false;
      return true;*/
      return (_vars[0] >= _end[0]);
    }
    T operator[](int d)
    {
      return _vars.at(d);
    }
    int numDimensions(){
      return dim();
    }
    std::vector<T>& getRaw(){
      return _vars;
    }
    

    };

        4
  •  1
  •   Soufiane Hassou    16 年前

    如果我理解您的要求,另一种方法是使用位运算符:

    for(int i = 0; i < 1<<size; i++) {
        for(int j = 0; j < size; j++) {
           if(i & 1<<j) printf("%d ", a[j]);
        }
        printf("\n");
    }
    
        5
  •  1
  •   Brian Postow    16 年前

    你需要一些东西来构造原始集的幂集。我写这个已经有一段时间了,但是psuedocode看起来像

    Powerset(a, size)
    {
       if(size == 0) return emptyset
    
       subseta = Powerset(a, size-1) // Powerset of everything except last element
       subsetb = appendToAll(a[size-1], subseta) // appends the last element to every set in subseta
       return union(subseta, subsetb)
    }