C++ 如何按排序顺序生成数组的所有排列?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17396222/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 21:09:51  来源:igfitidea点击:

How to generate all permutations of an array in sorted order?

c++permutation

提问by Code Geas Coder

I have an array, and the user can insert a string.

我有一个数组,用户可以插入一个字符串。

And I have this code:

我有这个代码:

int main(){
  char anagrama[13];
  cin >> anagrama;
  for(int j = 0; j < strlen(anagrama); j++){
    cout << anagrama[j];
    for(int k = 0; k < strlen(anagrama); k++){
      if(j != k)
        cout << anagrama[k];
    }
    cout << endl;
  }
}

The problem is that I need all permutationsof the string in sortedorder.

问题是我需要按排序顺序对字符串进行所有排列

For example if the user write: abc, the output must to be:

例如,如果用户写:abc,输出必须是:

abc
acb
bac
bca
cab
cba

and my code doesn't show all permutations, and not sorted

我的代码没有显示所有排列,也没有排序

Can you help me?

你能帮助我吗?

I need do the implementation without a function already implemented.

我需要在没有实现功能的情况下进行实现。

I think with a recursive function, but I do not know how.

我想用递归函数,但我不知道如何。

This is an example: http://www.disfrutalasmatematicas.com/combinatoria/combinaciones-permutaciones-calculadora.htmlwithout repetition and sorted

这是一个例子:http: //www.disfrutalasmatematicas.com/combinatoria/combinaciones-permutaciones-calculadora.html没有重复和排序

回答by dasblinkenlight

In C++ you can use std::next_permutationto go through permutations one by one. You need to sort the characters alphabetically before calling std::next_permutationfor the first time:

在 C++ 中,您可以使用std::next_permutation逐个排列。std::next_permutation在第一次调用之前,您需要按字母顺序对字符进行排序:

cin>>anagrama;
int len = strlen(anagrama);
sort(anagrama, anagrama+len);
do {
    cout << anagrama << endl;
} while (next_permutation(anagrama, anagrama+len));

Here is a demo on ideone.

这是ideone 上演示

If you must implement permutations yourself, you could borrow the source codeof next_permutation, or choose a simpler way of implementing a permutation algorithm recursively.

如果你必须自己实现的排列,你可以借用的源代码next_permutation,或选择递归实现置换算法的一个简单的方法。

回答by BLUEPIXY

#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

void permute(string select, string remain){
    if(remain == ""){
        cout << select << endl;
        return;
    }
    for(int i=0;remain[i];++i){
        string wk(remain);
        permute(select + remain[i], wk.erase(i, 1));
    }
}

int main(){
    string anagrama;
    cout << "input character set >";
    cin >> anagrama;
    sort(anagrama.begin(), anagrama.end());
    permute("", anagrama);
}


Another version

另一个版本

#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>

using namespace std;

void permute(string& list, int level, vector<string>& v){
    if(level == list.size()){
        v.push_back(list);
        return;
    }
    for(int i=level;list[i];++i){
        swap(list[level], list[i]);
        permute(list, level + 1, v);
        swap(list[level], list[i]);
    }
}

int main(){
    string anagrama;
    vector<string> v;
    cout << "input character set >";
    cin >> anagrama;
    permute(anagrama, 0, v);
    sort(v.begin(), v.end());
    copy(v.begin(), v.end(), ostream_iterator<string>(cout, "\n"));
}

回答by akhileshzmishra

/*Think of this as a tree. The depth of the tree is same as the length of string.
In this code, I am starting from root node " " with level -1. It has as many children as the characters in string. From there onwards, I am pushing all the string characters in stack.
Algo is like this:

1. Put root node in stack.
2. Loop till stack is empty
2.a If backtracking
2.a.1 loop from last of the string character to present depth or level and reconfigure datastruture.
2.b Enter the present char from stack into output char

2.c If this is leaf node, print output and continue with backtracking on.
2.d Else find all the neighbors or children of this node and put it them on stack. */



        class StringEnumerator
        {
        char* m_string;
        int   m_length;
        int   m_nextItr;
        public:
        StringEnumerator(char* str, int length): m_string(new char[length + 1]), m_length(length)  , m_Complete(m_length, false)
        {
        memcpy(m_string, str, length);
        m_string[length] = 0;
        }
    StringEnumerator(const char* str, int length): m_string(new char[length + 1]), m_length(length)  , m_Complete(m_length, false)
    {
        memcpy(m_string, str, length);
        m_string[length] = 0;
    }
    ~StringEnumerator()
    {
        delete []m_string;
    }

    void Enumerate();
   };


        const int MAX_STR_LEN = 1024;
        const int BEGIN_CHAR = 0;

        struct StackElem
        {  
      char Elem;
      int Level;
      StackElem(): Level(0), Elem(0){}
      StackElem(char elem, int level): Elem(elem), Level(level){}

        };

        struct CharNode
        {
      int Max;
      int Curr;
      int Itr;
      CharNode(int max = 0): Max(max), Curr(0), Itr(0){}
      bool IsAvailable(){return (Max > Curr);}
      void Increase()
      {
        if(Curr < Max)
            Curr++;
      }
      void Decrease()
      {
        if(Curr > 0)
            Curr--;
       }
       void PrepareItr()
      {
        Itr = Curr;
       }
};




        void StringEnumerator::Enumerate()
{

    stack<StackElem> CStack;
    int count = 0;
    CStack.push(StackElem(BEGIN_CHAR,-1));
    char answerStr[MAX_STR_LEN];
    memset(answerStr, 0, MAX_STR_LEN);

    bool forwardPath = true;

    typedef std::map<char, CharNode> CharMap;

    typedef CharMap::iterator CharItr;
    typedef std::pair<char, CharNode> CharPair;

    CharMap mCharMap;
    CharItr itr;

    //Prepare Char Map
    for(int i = 0; i < m_length; i++)
    {
        itr = mCharMap.find(m_string[i]);
        if(itr != mCharMap.end())
        {
            itr->second.Max++;
        }
        else
        {
            mCharMap.insert(CharPair(m_string[i], CharNode(1)));
        }
    }


    while(CStack.size() > 0)
    {
        StackElem elem = CStack.top();
        CStack.pop();

        if(elem.Level != -1)     // No root node
        {
            int currl = m_length - 1;
            if(!forwardPath)
            {
                while(currl >= elem.Level)
                {
                    itr = mCharMap.find(answerStr[currl]);
                    if((itr != mCharMap.end()))
                    {
                        itr->second.Decrease();
                    }
                    currl--;
                }

                forwardPath = true;
            }

            answerStr[elem.Level] = elem.Elem;

            itr = mCharMap.find(elem.Elem);
            if((itr != mCharMap.end()))
            {
                itr->second.Increase();
            }
        }

        //If leaf node
        if(elem.Level == (m_length - 1))
        {
            count++;
            cout<<count<<endl;
            cout<<answerStr<<endl;
            forwardPath = false;
            continue;
        }

        itr = mCharMap.begin();

        while(itr != mCharMap.end())
        {
            itr->second.PrepareItr();
            itr++;
        }


        //Find neighbors of this elem 
        for(int i = 0; i < m_length; i++)
        {
            itr = mCharMap.find(m_string[i]);
            if(/*(itr != mCharMap.end()) &&*/ (itr->second.Itr < itr->second.Max))
            {
                CStack.push(StackElem(m_string[i], elem.Level + 1));
                itr->second.Itr++;
            }
        }


    }


}

回答by ARK

@alexander the output of this programme is in exact order as requested by you:

@alexander 该程序的输出与您要求的顺序完全相同:

HERE, is a simplest code for generating all combination/permutations of a given array without including some special libraries (only iostream.hand stringare included) and without using some special namespaces than usual ( only namespace stdis used).

这里是一个最简单的代码,用于生成给定数组的所有组合/排列,不包括一些特殊的库(仅包含iostream.hstring)并且不使用一些比平常更特殊的命名空间(仅使用命名空间 std)。

void shuffle_string_algo( string ark )
{

//generating multi-dimentional array:

char** alpha = new char*[ark.length()];
for (int i = 0; i < ark.length(); i++)
    alpha[i] = new char[ark.length()];

//populating given string combinations over multi-dimentional array
for (int i = 0; i < ark.length(); i++)
    for (int j = 0; j < ark.length(); j++)
        for (int n = 0; n < ark.length(); n++)
            if( (j+n) <= 2 * (ark.length() -1) )
                if( i == j-n)
                    alpha[i][j] = ark[n];
                else if( (i-n)== j)
                    alpha[i][j] = ark[ ark.length() - n];

if(ark.length()>=2)
{
    for(int i=0; i<ark.length() ; i++)
    {
        char* shuffle_this_also = new char(ark.length());
        int j=0;
        //storing first digit in golobal array ma
        ma[v] = alpha[i][j];

        //getting the remaning string
        for (; j < ark.length(); j++)
            if( (j+1)<ark.length())
                shuffle_this_also[j] = alpha[i][j+1];
            else
                break;
        shuffle_this_also[j]='
int main()
{
string a;
int ch;
do
{
    system("CLS");
    cout<<"PERMUNATING BY ARK's ALGORITH"<<endl;
    cout<<"Enter string: ";
    fflush(stdin);
    getline(cin, a);

    ma = new char[a.length()];

    shuffle_string_algo(a);

    cout<<"Do you want another Permutation?? (1/0): ";
    cin>>ch;
} while (ch!=0);

return 0;
}
'; //converting to string string send_this(shuffle_this_also); //checking if further combinations exist or not if(send_this.length()>=2) { //review the logic to get the working idea of v++ and v-- v++; shuffle_string_algo( send_this); v--; } else { //if, further combinations are not possiable print these combinations ma[v] = alpha[i][0]; ma[++v] = alpha[i][1]; ma[++v] = '
#include <iostream>
#define N 4
using namespace std;

char ch[] = "abcd";

int func(int n) {
    int i,j;
    char temp;
    if(n==0) {
        for(j=N-1;j>=0;j--)
            cout<<ch[j];
        cout<<endl;
        return 0;
    }
    for(i=0;i<n;i++){
        temp = ch[i];
        for(j=i+1;j<n;j++)
            ch[j-1] = ch[j];
        ch[n-1] = temp;
        //shift
        func(n-1);
        for(j=n-1;j>i;j--)
            ch[j] = ch[j-1];
        ch[i] = temp;
        //and shift back agian
    }
    return 1;
}

int main(void)
{
    func(N);
    return 0;
}
'; v=v-2; string disply(ma); cout<<++permutaioning<<":\t"<<disply<<endl; } } } }

and main:

主要

#include <iostream>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <boost/algorithm/string/join.hpp>
using namespace std;

int main() {
    // your code goes here
    std::vector<std::string> s;
    s.push_back("abc");
    s.push_back("def");
    s.push_back("ghi");

    std::sort(s.begin(), s.end());
    do
    {
      std::cout << boost::algorithm::join(s,"_") << std::endl ;
    } while(std::next_permutation(s.begin(), s.end())); 
    return 0;
}

HOPE! it helps you! if you are having problem with understanding logic just comment below and i will edit.

希望!它可以帮助你!如果您在理解逻辑方面遇到问题,请在下面发表评论,我会进行编辑。

回答by vvy

I wrote one without a function already implemented even any templates and containers. actually it was written in C first, but has been transform to C++.

我写了一个没有实现任何模板和容器的功能。实际上它最初是用 C 编写的,但已转换为 C++。

easy to understand but poor efficiency, and its output is what you want, sorted.

简单易懂但效率低下,而且它的输出是你想要的,排序的。

##代码##

回答by Mitendra

In case you have std::vector of strings then you can 'permute' the vector items as below.

如果您有 std::vector 字符串,那么您可以“置换”向量项,如下所示。

C++14 Code

C++14 代码

##代码##

Output:

输出

abc_def_ghi

abc_def_ghi

abc_ghi_def

abc_ghi_def

def_abc_ghi

def_abc_ghi

def_ghi_abc

def_ghi_abc

ghi_abc_def

ghi_abc_def

ghi_def_abc

ghi_def_abc