2013-07-01 228 views
17

我有一个数组,并且用户可以插入一个字符串。如何按排序顺序生成数组的所有排列?

而且我有这样的代码:

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没有重复和分类

+0

鉴于“没有已经实现的功能”意味着作业,所以我不会给出完整的代码。是的,你可以使用递归。遍历字符串中的字符,每次删除该字符,以便它可以将尚未使用的字符传递给它自己。一个合理的函数签名将是'void f(std :: vector &results,const std :: string&unused_chars,const std :: string&prefix_so_far =“”)''。如果'f'发现'unused_chars'为空,它可以将'prefix_so_far'添加到'results'。 –

+0

组合不同于排列(你的例子)。在组合中,元素的顺序无关紧要,顺序在排列中很重要。 – rendon

+0

将所有组合推入矢量,然后对其进行排序。 –

回答

33

在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

如果您必须自己实现排列,可以使用borrow the source codenext_permutation,或者选择递归实现排列算法的更简单的方法。

+0

不,我需要实现的排列,我不能使用函数 –

+0

我意图实现递归排列算法,但我有一些问题 –

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

好的,但是什么是字符串(wk)。这个功能是什么? –

+0

我如何分类输出? –

+0

@AlexanderOvalle'wk(remain)'构造函数。保持复制到周。 – BLUEPIXY

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

不太容易理解。 –

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


    } 


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

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