数组中字符的排列

Permutations of characters in an array

本文关键字:排列 字符 数组      更新时间:2023-10-16

我输入了一个字符数组,并希望获得该数组的所有可能组合作为输出。例如,如果我输入字符数组=‘a,b,c’,我想要这种形式的输出:

a b c,
a c b,
b a c,
b c a,
c a b,
c b a

类似地,如果我输入4个字符,我想从中得到24个组合。我已经为此编写了一个代码,但它只返回输入字符量的2倍的组合。也就是说,如果我输入3个字符(没错),代码会返回6个组合,但如果我输入4个字符,它只返回8个可能的组合,而不是24个组合。我的代码如下:

#include <iostream>
#include<string.h>
#include<stdio.h>
using std::cout;
void getCombination(char *);
int main()
{
    const int maxStringSize = 26;
    char thisString[maxStringSize];
    cout<<"Enter String = ";
    gets (thisString);
    getCombination(thisString);
    return 0;
}
void getCombination(char *thisString)
{
    int stringSize=strlen(thisString);
    for(int i = 0; i<stringSize; i++)
    {
        for(int j = 0; j<stringSize; j++)
        {
            cout<<thisString[(i+j)%stringSize];
        }
        cout<<"n";
        for(int k = stringSize-1; k>=0; k--)
        {
            cout<<thisString[(i+k)%stringSize];
        }
    cout<<"n";
    }
}

http://www.sgi.com/tech/stl/next_permutation.html

std::next_preputation应该有助于您进行

为什么您的代码失败

你的代码会产生2次排列,因为这就是你正在做的。您要选择一个前缀,然后按顺序和相反顺序打印字符串,也就是说,每个前缀有两个输出。总数=n*2。(这样你怎么可能打印所有排列?)

解决方案

您需要的是std::next_placement。记住在下一次传递数组之前对数组进行排序,它会按递增顺序生成排列,这正是您所需要的(根据您的示例)。

您可以在这里阅读有关生成正确输出的递归实现,以及next_placement是如何在C++中实现的。

关于术语的评论:这些被称为排列,而不是组合。

这是因为你只看到由以下组成的排列:

  • 选择第一个字母
  • 将其余部分整理好,或者
  • 把剩下的倒过来

特别是,你永远不能用这种方式从abcd形成acbd

我建议第一次尝试递归解决方案(选择第一个字母,然后查看其余字母的所有排列)。

然后,如果您担心过多的递归调用会导致堆栈溢出,那么从递归解决方案中,您可以创建一个使用类似堆栈的数据结构的解决方案。

您可以使用标准库的算法部分中的std::next_permutation来完成此操作。有关示例,请参阅下面的代码片段。请注意,我首先对theString进行排序,因为这是next_permutation查找所有组合所必需的。

#include <iostream>
#include <algorithm>
int main()
{
    std::string theString = "abc";
    std::sort(theString.begin(), theString.end()); 
    do
    {
        std::cout << theString << std::endl;
    }
    while (std::next_permutation(theString.begin(), theString.end()));
    return 0;
}

我想可以这样做:

void swap( char &a, char &b) {
char c=a;
a = b;
b = c;
}

void get_Combination( string word, int d ) {
if (d == word.size()) {
    cout<<word<<endl;
    return;
}
for (int i=d; i< word.size(); ++i) {
    swap(word[i],word[d]);
    get_combination( word, d+1 );
    swap(word[i],word[d]);
}
}

说明:U首先调用get_combination(word,0)。现在要找到字符串的所有排列,每个位置的每个字符都应该出现在一个或其他排列的第一个位置。因此,我们从d=0开始,并交换每个字符,直到字符串末尾的字符为d。在第一个字符就位后,我们通过调用get_combination(单词,d+1)从第二个字符开始重复该过程。还要注意第二次交换,它需要将最初交换的字符带回它们的原始位置,然后用位置d的字符交换下一个字符。

示例:

给定字符串abc,这里是递归树,gc=get_combination

gc("abc",0)
   gc(abc,1)
      gc(abc,2)
        cout<<"abc"
      gc(acb,2)
        cout<<"acb"
   gc(bac,1)
      gc(bac,2)
        cout<<"bac"
      gc(bca,2)
        cout<<"bca"
  gc(cba,1)
      gc(cba,2)
        cout<<"cba"
      gc(cab,2)
        cout<<"cab"