【问题标题】:Making an algorithm for listing all possible sequences制作列出所有可能序列的算法
【发布时间】:2013-04-18 10:42:51
【问题描述】:

我需要一些关于如何使用数组来打印所有可能序列的想法。 例如,

array 1: AA BB
array 2: CC
array 3: DD EE FF
array 4: GG

现在我需要列出来自任何给定数组的所有可能组合,每个数组仅使用 1 个序列,如下所示:

AA CC DD GG
AA CC EE GG
AA CC FF GG
BB CC DD GG
BB CC EE GG
BB CC FF GG

有谁知道或可以让我开始了解如何做到这一点?

【问题讨论】:

  • 注意:这是一个基本的 c++ 类,所以我需要为此使用基本方法,而不是向量或任何东西
  • 正如我所说,我需要一个不使用向量的基本方法,所以这个问题对我没有帮助
  • 转换为非向量解决方案是微不足道的。代替迭代器,使用索引。算法是一样的。此外,您要求“某种想法”,而其他解决方案是一个非常好的想法。不能使用向量的限制是人为的,不切实际的。此外,请务必在作业中说明您从 StackOverflow 获得了答案,符合 SO 许可证(需要注明出处)以及学术诚信规则。

标签: c++ arrays algorithm


【解决方案1】:

我假设您的意思是每个数组的元素数量是未知的,为此我使用了 sizeof()。 就像其他人提到的那样,您只需嵌套 5 个 for 循环。

int main()
{
    //naming arrays a,b,c,d,e, change accordingly
    //this function prints the combinations of 1 char
    int aElements = sizeof(a) / sizeof(a[0]);
    int bElements = sizeof(b) / sizeof(b[0]);
    int cElements = sizeof(c) / sizeof(c[0]);
    int dElements = sizeof(d) / sizeof(d[0]);
    int eElements = sizeof(e) / sizeof(e[0]);
    for (int i = 0; i < aElements; i++){
        for (int j = 0; j < bElements; j++){
            for (int k = 0; k < cElements; k++){
                for (int l = 0; l < dElements; l++){
                    for (int m = 0; m < eElements; m++){
                        cout << a[i] << b[j] << c[k] << d[l] << e[m] << endl;
                    }
                }
            }
        }
    }
}

为了找出组合的数量,您可以在内部循环中放置一个计数器,或者只需将元素数量除以组合数量(在本例中为 1),然后将它们全部相乘。例如,在您的示例中,它将是 (4 / 1) * (2 / 1) * (2 / 1) * (6 / 1) * (2 / 1) = 192 种组合。如果您每 2 个字符进行组合,则在第二个示例中它将是 (4 / 2) * (2 / 2) * (2 / 2) * (6 / 2) * (2 / 2) = 6 个组合。以下函数打印出 2 的组合。

int main()
    {
    //naming arrays a,b,c,d,e, change accordingly
    //this function prints the combinations of 2 chars
    int aElements = sizeof(a) / sizeof(a[0]);
    int bElements = sizeof(b) / sizeof(b[0]);
    int cElements = sizeof(c) / sizeof(c[0]);
    int dElements = sizeof(d) / sizeof(d[0]);
    int eElements = sizeof(e) / sizeof(e[0]);
    for (int i = 0; i < aElements - 1; i+=2){
        for (int j = 0; j < bElements - 1; j+=2){
            for (int k = 0; k < cElements - 1; k+=2){
                for (int l = 0; l < dElements - 1; l+=2){
                    for (int m = 0; m < eElements - 1; m+=2){
                        cout << a[i] << a[i+1] << b[j] << b[j+1] << c[k] << c[k+1]  << d[l] << d[l+1] << e[m] << e[m+1] << endl;
                        }
                    }
                }
            }
        }
}

我为第二次所做的只是将计数器增加 2 而不是 1,从元素数量中减去 1 以不超出界限,并打印 2 个连续元素而不是 1。这适用于任意数量的字符组合。

【讨论】:

  • 谢谢,这解决了我所有的问题。我可以将其复制粘贴到我的代码中吗?
  • 您不能按原样复制和粘贴,我建议制作包含每个示例的 2 个单独的函数。我还建议看看它是如何工作的,并编写自己的函数,而不仅仅是复制。最后,我在编程方面相对较新,所以这可能不是一个理想的解决方案,你也许可以写出更好的东西。
  • 我将使用这个示例,因为在我的 c++ 课程中,我们没有讨论向量或任何其他高级主题,只是到目前为止的基础知识。这对我来说似乎很理想,不过感谢所有答案
  • 啊,难怪,老实说,我有点惊讶你选择了我的答案
【解决方案2】:

如果这些是 4 个不同的数组,我想不出更好的选择,然后编写 4 个嵌套循环,每个循环遍历其中一个数组。如果您有一个包含所有数组的二维数组,我建议您使用递归。

【讨论】:

    【解决方案3】:

    C++11 风格!

    #include <iostream>
    #include <vector>
    #include <utility>
    #include <iterator>
    
    // metaprogramming boilerplate:
    
    template<typename... L>
    struct first_type {};
    template<typename T, typename... L>
    struct first_type<T, L...> {
      typedef T type;
    };
    template<typename... L>
    using FirstType = typename first_type<L...>::type;
    
    namespace aux {
        using std::begin;
        template<typename C>
        auto adl_begin( C&&c )->decltype( begin(std::forward<C>(c)) );
        template<typename C>
        auto adl_cbegin( C const&c )->decltype( begin(c) );
    }
    template<typename Container>
    struct iterator_type {
      typedef decltype( aux::adl_begin(std::declval<Container>()) ) iterator;
      typedef decltype( aux::adl_cbegin(std::declval<Container>()) ) const_iterator;
    };
    template<typename Container>
    using IteratorType = typename iterator_type<Container>::iterator;
    
    template<typename Container>
    struct value_type {
      typedef typename std::iterator_traits< IteratorType<Container> >::value_type type;
    };
    template<typename Container>
    using ValueType = typename value_type<Container>::type;
    
    // Actual problem specific code:
    template<typename Func, typename T>
    void ForEachPossibility_Helper( Func&& f, std::vector<T>& result) {
      f(result);
    }
    
    template<typename Func, typename T, typename Container, typename... Containers>
    void ForEachPossibility_Helper( Func&& f, std::vector<T>& result, Container&& arr0, Containers&&... arrays) {
      for( auto const& str:arr0 ) {
        result.push_back(str);
        ForEachPossibility_Helper( std::forward<Func>(f), result, std::forward<Containers>(arrays)... );
        result.pop_back();
      }
    }
    
    template<typename Func, typename... Containers>
    void ForEachPossibility( Func&& f, Containers&&... arrays) {
        typedef ValueType<FirstType<Containers...>> T;
        std::vector<T> result;
        ForEachPossibility_Helper( std::forward<Func>(f), result, std::forward<Containers>(arrays)... );
    }
    
    const char* arr1[] = {"AA", "BB"};
    const char* arr2[] = {"CC"};
    const char* arr3[] = {"DD", "EE", "FF"};
    const char* arr4[] = {"GG"};
    
    int main() {
      ForEachPossibility( []( std::vector<const char*> const& result ){
        for( auto&& str:result ) {
          std::cout << str;
        }
        std::cout << "\n";
      }, arr1, arr2, arr3, arr4 );
    }
    

    请注意,只有 2 个 for 循环,其中一个用于打印。

    【讨论】:

    • @interrminatelysequenced 呸,我只是注意到我缺少decltypestd::vector&lt;decltype( *std::begin( arr0 ) )&gt; 数据类型的推导(而是我使用了std::vector&lt; const char* &gt;。哦,好吧。
    • 我们仍然没有在我的 c++ 类中检查向量,所以很遗憾我不能使用它,不过谢谢
    • @Yakk nitpick:你可能不应该将这些变量命名为 stacklist,即使这里没有歧义。
    • @indeterminatelysequenced 是的,有。它现在可以与任何容器类型一起使用作为奖励(不仅仅是const char* 的容器)。遗憾的是,这需要编写一个小型元编程库。
    • @Foxic 在覆盖std::vector 之前,您不想在课堂上将其作为问题的答案提交有很多原因。 :)
    【解决方案4】:

    据我所知,您不需要关心从中获取序列的数组的顺序。在这种情况下,递归确实很有帮助。看起来有点像:

    void printSequences(ListOfYourArrays list, int index) {
        if (list.size() > index) {
            array a = list.getElementAt(index);
            //Make a cycle that reads items from your array one by one
            while (...)
                System.out.print(item);
            //And now you need to print all combinations for the rest of arrays in you list
            printSequences(list, index + 1);
        } else
            System.out.println();
    }
    

    你需要做的就是将你的数组添加到列表中并调用一个函数

    printSequences(list, 0);
    

    【讨论】:

    • 这将打印AA BB ...
    【解决方案5】:

    如果您有可变数量的数组,Tocs 的答案是正确的。如果你总是有 4 个数组,你可以简单地使用 4 个嵌套循环。

       for (unsigned int i1 = 0; i1 < a1.size(); ++i1)
            for (unsigned int i2 = 0; i2 < a2.size(); ++i2)
                for (unsigned int i3 = 0; i3 < a3.size(); ++i3)
                    for (unsigned int i4 = 0; i4 < a4.size(); ++i4)
                        cout << a1[i1] << " " << a2[i2] << " " << a3[i3] << " " << a4[i4] << std::endl;
    

    完整代码见这里http://ideone.com/YcW84Q

    【讨论】:

      【解决方案6】:

      为更新而编辑

      我们需要通过迭代组合来更新每个索引,而不是更新...

      见:How can I iterate throught every possible combination of n playing cards

      所以现在看起来像这样

      #include <iostream>
      #include <vector>
      #include <string>
      using namespace std;
      
      bool UpdateCombination (std::vector<int> &comboindices, int count, int n)
      {
          for (int i = 1; i <= n; ++i)
          {
              if (comboindices[n - i] < count - i)
              {
                  ++comboindices[n - i];
                  for (int j = n - i + 1; j < n; ++j)
                  {
                      comboindices[j] = comboindices[j-1] + 1;
                  }
                  return false;
              }
          }
          return true;
      }
      
      void ResetCombination (std::vector<int> &comboindices, int n)
      {
          comboindices.resize(n);
          for (int i = 0; i < n; ++i)
          {
              comboindices[i] = i;
          }
      }
      
      void PrintArrays (const std::vector<std::vector<std::string>> items, int count)
      {
          std::vector<std::vector<int>> indices;
          int n = items.size();
          indices.resize(items.size());
      
          for(auto i = indices.begin (); i != indices.end (); ++i)
          {
              ResetCombination((*i),count);
          }
      
          while (true) //Iterate until we've used all of the last array of items
          {
                  for (int i = 0; i < n; ++i)
                  {
                      cout << "{";
                      for (auto j = indices[i].begin (); j != indices[i].end (); ++j)
                      {
                          int ji = (*j);
                          cout << (items[i])[ji] << " ";
                      }
                      cout << "} ";
      
                  }
                  cout << endl;
      
                  //Update to the next indice
                  for (int i = n - 1; i >= 0; --i)
                  {
                          bool done = UpdateCombination (indices[i],items[i].size(),count);
                          if (!done)
                          {
                                  break;
                          }
                          else if (done && i == 0)
                          {
                              return; //Escape.
                          }
                          else
                          {
                              ResetCombination(indices[i],count);
                          }
                  }
          }
      
      }
       //{A,B,C,D},{A,B},{A,B},{A,B,C,D,E,F},{A,B}
      
      
      int main() {
      
          vector<vector<string>> lists;
          lists.resize(5);
          lists[0].push_back("A");
          lists[0].push_back("B");
          lists[0].push_back("C");
          lists[0].push_back("D");
      
          lists[1].push_back("A");
          lists[1].push_back("B");
      
          lists[2].push_back("A");
          lists[2].push_back("B");
      
          lists[3].push_back("A");
          lists[3].push_back("B");
          lists[3].push_back("C");
          lists[3].push_back("D");
          lists[3].push_back("E");
          lists[3].push_back("F");
      
          lists[4].push_back("A");
          lists[4].push_back("B");
      
      
      
          PrintArrays(lists,2);
      
          int pause;
          cin >> pause;
          return 0;
      }
      

      给我们...

      {A B } {A B } {A B } {A B } {A B } 
      {A B } {A B } {A B } {A C } {A B } 
      {A B } {A B } {A B } {A D } {A B } 
      {A B } {A B } {A B } {A E } {A B } 
      {A B } {A B } {A B } {A F } {A B } 
      {A B } {A B } {A B } {B C } {A B } 
      {A B } {A B } {A B } {B D } {A B } 
      {A B } {A B } {A B } {B E } {A B } 
      {A B } {A B } {A B } {B F } {A B } 
      {A B } {A B } {A B } {C D } {A B } 
      {A B } {A B } {A B } {C E } {A B } 
      {A B } {A B } {A B } {C F } {A B } 
      {A B } {A B } {A B } {D E } {A B } 
      {A B } {A B } {A B } {D F } {A B } 
      {A B } {A B } {A B } {E F } {A B } 
      {A C } {A B } {A B } {A B } {A B } 
      {A C } {A B } {A B } {A C } {A B } 
      {A C } {A B } {A B } {A D } {A B } 
      {A C } {A B } {A B } {A E } {A B } 
      {A C } {A B } {A B } {A F } {A B } 
      {A C } {A B } {A B } {B C } {A B } 
      {A C } {A B } {A B } {B D } {A B } 
      {A C } {A B } {A B } {B E } {A B } 
      {A C } {A B } {A B } {B F } {A B } 
      {A C } {A B } {A B } {C D } {A B } 
      {A C } {A B } {A B } {C E } {A B } 
      {A C } {A B } {A B } {C F } {A B } 
      {A C } {A B } {A B } {D E } {A B } 
      {A C } {A B } {A B } {D F } {A B } 
      {A C } {A B } {A B } {E F } {A B } 
      {A D } {A B } {A B } {A B } {A B } 
      {A D } {A B } {A B } {A C } {A B } 
      {A D } {A B } {A B } {A D } {A B } 
      {A D } {A B } {A B } {A E } {A B } 
      {A D } {A B } {A B } {A F } {A B } 
      {A D } {A B } {A B } {B C } {A B } 
      {A D } {A B } {A B } {B D } {A B } 
      {A D } {A B } {A B } {B E } {A B } 
      {A D } {A B } {A B } {B F } {A B } 
      {A D } {A B } {A B } {C D } {A B } 
      {A D } {A B } {A B } {C E } {A B } 
      {A D } {A B } {A B } {C F } {A B } 
      {A D } {A B } {A B } {D E } {A B } 
      {A D } {A B } {A B } {D F } {A B } 
      {A D } {A B } {A B } {E F } {A B } 
      {B C } {A B } {A B } {A B } {A B } 
      {B C } {A B } {A B } {A C } {A B } 
      {B C } {A B } {A B } {A D } {A B } 
      {B C } {A B } {A B } {A E } {A B } 
      {B C } {A B } {A B } {A F } {A B } 
      {B C } {A B } {A B } {B C } {A B } 
      {B C } {A B } {A B } {B D } {A B } 
      {B C } {A B } {A B } {B E } {A B } 
      {B C } {A B } {A B } {B F } {A B } 
      {B C } {A B } {A B } {C D } {A B } 
      {B C } {A B } {A B } {C E } {A B } 
      {B C } {A B } {A B } {C F } {A B } 
      {B C } {A B } {A B } {D E } {A B } 
      {B C } {A B } {A B } {D F } {A B } 
      {B C } {A B } {A B } {E F } {A B } 
      {B D } {A B } {A B } {A B } {A B } 
      {B D } {A B } {A B } {A C } {A B } 
      {B D } {A B } {A B } {A D } {A B } 
      {B D } {A B } {A B } {A E } {A B } 
      {B D } {A B } {A B } {A F } {A B } 
      {B D } {A B } {A B } {B C } {A B } 
      {B D } {A B } {A B } {B D } {A B } 
      {B D } {A B } {A B } {B E } {A B } 
      {B D } {A B } {A B } {B F } {A B } 
      {B D } {A B } {A B } {C D } {A B } 
      {B D } {A B } {A B } {C E } {A B } 
      {B D } {A B } {A B } {C F } {A B } 
      {B D } {A B } {A B } {D E } {A B } 
      {B D } {A B } {A B } {D F } {A B } 
      {B D } {A B } {A B } {E F } {A B } 
      {C D } {A B } {A B } {A B } {A B } 
      {C D } {A B } {A B } {A C } {A B } 
      {C D } {A B } {A B } {A D } {A B } 
      {C D } {A B } {A B } {A E } {A B } 
      {C D } {A B } {A B } {A F } {A B } 
      {C D } {A B } {A B } {B C } {A B } 
      {C D } {A B } {A B } {B D } {A B } 
      {C D } {A B } {A B } {B E } {A B } 
      {C D } {A B } {A B } {B F } {A B } 
      {C D } {A B } {A B } {C D } {A B } 
      {C D } {A B } {A B } {C E } {A B } 
      {C D } {A B } {A B } {C F } {A B } 
      {C D } {A B } {A B } {D E } {A B } 
      {C D } {A B } {A B } {D F } {A B } 
      {C D } {A B } {A B } {E F } {A B }
      

      查看输出。 http://ideone.com/L5AZVv

      旧ideone链接: http://ideone.com/58ARAZ

      【讨论】:

        【解决方案7】:

        另一种可能性是“计数”当前组合(例如,计数二进制)。从 (0,0,0,0) 开始并计数到最大数组索引 (1,0,2,0)。在每一步中,首先将第一个索引加 1。如果大于最大索引(此处为 1),则将其设置为零并继续下一个索引

        结果:

        (0,0,0,0) --> AA CC DD GG

        (1,0,0,0) --> BB CC DD GG

        (0,0,1,0) --> AA CC EE GG

        (1,0,1,0) --> BB CC EE GG

        (0,0,2,0) --> AA CC FF GG

        (1,0,2,0) --> BB CC FF GG

        【讨论】:

          【解决方案8】:

          4 个循环导致 N pow(4)。

          拆分 4 个循环成 2 个的数组。

          for each(arr 1){
            for each(arr 2)
            insert into container 1.
          }
          
          
          for each(arr 3){
            for each(arr 4)
            insert into container 2.
          }
          
          
          for each(container 1){
            for each(container 2)
            insert into container3 (*iter 1 + *iter 2)
          }
          

          所以复杂度最大为 3NPow(2),小于 N pow(4)

          【讨论】:

          • 不复杂不会改变这样做..!!对于第一个循环,它是 NPow(2),第二个循环是 Npow(2),对于第三个循环,它是 (M)Pow(2),这里 M= NPow(2) 你说的容器大小是 NPow(2)。 .!!所以它不会改变,最后是 NPow(4)..!
          猜你喜欢
          • 1970-01-01
          • 2020-11-01
          • 2023-04-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-02-04
          • 1970-01-01
          相关资源
          最近更新 更多