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

时间:2013-07-01 00:52:01

标签: c++ permutation

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

我有这段代码:

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;
  }
}

问题在于我需要排序顺序中字符串的所有排列

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

abc
acb
bac
bca
cab
cba

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

你能帮助我吗?

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

我认为使用递归函数,但我不知道如何。

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

6 个答案:

答案 0 :(得分:44)

在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));

这是demo on ideone

如果您必须自己实现排列,可以next_permutation {{1}},或者选择一种更简单的递归方式实现排列算法。

答案 1 :(得分:11)

#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);
}

另一个版本

#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"));
}

答案 2 :(得分:2)

/*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++;
            }
        }


    }


}

答案 3 :(得分:2)

@alexander此程序的输出按照您的要求准确排序:

这里是一个最简单的代码,用于生成给定数组的所有组合/排列,而不包括一些特殊的库(仅包括 iostream.h 字符串)使用一些特殊的命名空间(仅使用命名空间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]='\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] = '\0';
            v=v-2;

            string disply(ma);
            cout<<++permutaioning<<":\t"<<disply<<endl;
        }
    }
}
}

主要

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;
}

HOPE!它可以帮助你!如果您在理解逻辑时遇到问题,请在下面进行评论,我将进行编辑。

答案 4 :(得分:1)

我写了一个没有功能的功能,甚至已经实现了任何模板和容器。实际上它首先用C语言编写,但已经转换为C ++。

易于理解但效率低下,其输出是您想要的,排序。

#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;
}

答案 5 :(得分:0)

如果您有字符串的std :: vector,则可以如下所示“置换”矢量项。

C ++ 14代码

#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;
}

输出

abc_def_ghi

abc_ghi_def

def_abc_ghi

def_ghi_abc

ghi_abc_def

ghi_def_abc