我想按字典顺序打印字符串的所有排列。我写了这段代码:
void permute(char *a, int i, int n) { if (i == (n-1)) printf("\"%s\"\n", a); else { for (int j = i; j < n; j++) { swap((a+i), (a+j)); permute(a, i+1, n); swap((a+i), (a+j)); } } }
让我们以string为例abc,我想按字典顺序接收所有排列,如左列所示,但结果如右列所示。
abc
"abc" "abc" "acb" "acb" "bac" "bac" "bca" "bca" "cab" < "cba" "cba" > "cab"
有人可以帮我弄这个吗?我看到了一些算法,但是看起来很困难。我想我可以将所有生成的字符串保存在一个数组中,然后对该数组进行排序,但是我不能写这个(我是C语言的初学者)。
在geeksforgeeks上有一个非常简单的算法描述(包括实现):
给定一个字符串,按排序顺序打印它的所有排列。例如,如果输入字符串为“ ABC”,则输出应为“ ABC,ACB,BAC,BCA,CAB,CBA”。 我们在本文中讨论了一个打印所有排列的程序,但是在这里我们必须按升序打印排列。 以下是按词典顺序打印排列的步骤 以非降序对给定的字符串进行排序并打印。第一个排列始终是按非降序排序的字符串。 开始生成下一个更高的排列。直到无法进行更高的排列为止。如果我们达到一个排列,其中所有字符都以非递增顺序排序,那么该排列就是最后的排列。 生成下一个较高排列的步骤: 1.进行先前打印的排列,并在其中找到最右边的字符,该字符小于下一个字符。让我们将此字符称为“第一个字符”。 现在找到“第一个角色”的上限。天花板是“第一个字符”右侧的最小字符,大于“第一个字符”。让我们将ceil字符称为“第二个字符”。 交换在以上两个步骤中找到的两个字符。 在“第一个字符”的原始索引之后对子字符串进行排序(以不降序排列)。
给定一个字符串,按排序顺序打印它的所有排列。例如,如果输入字符串为“ ABC”,则输出应为“ ABC,ACB,BAC,BCA,CAB,CBA”。
我们在本文中讨论了一个打印所有排列的程序,但是在这里我们必须按升序打印排列。
以下是按词典顺序打印排列的步骤
以非降序对给定的字符串进行排序并打印。第一个排列始终是按非降序排序的字符串。
开始生成下一个更高的排列。直到无法进行更高的排列为止。如果我们达到一个排列,其中所有字符都以非递增顺序排序,那么该排列就是最后的排列。
生成下一个较高排列的步骤: 1.进行先前打印的排列,并在其中找到最右边的字符,该字符小于下一个字符。让我们将此字符称为“第一个字符”。
现在找到“第一个角色”的上限。天花板是“第一个字符”右侧的最小字符,大于“第一个字符”。让我们将ceil字符称为“第二个字符”。
交换在以上两个步骤中找到的两个字符。
在“第一个字符”的原始索引之后对子字符串进行排序(以不降序排列)。
我在下面重新实现了它:
#include <stdio.h> #include <string.h> #include <stdlib.h> void swap(char* left, char* right) { char temp = *left; *left = *right; *right = temp; } int compare (const void * a, const void * b) { return ( *(char*)a - *(char*)b ); } void PrintSortedPermutations(char* inStr) { // Re-implementation of algorithm described here: // http://www.geeksforgeeks.org/lexicographic-permutations-of-string/ int strSize = strlen(inStr); // 0. Ensure input container is sorted qsort(inStr, strSize, sizeof(char), compare); int largerPermFound = 1; do{ // 1. Print next permutation printf("%s\n", inStr); // 2. Find rightmost char that is smaller than char to its right int i; for (i = strSize - 2; i >= 0 && inStr[i] >= inStr[i+1]; --i){} // if we couldn't find one, we're finished, else we can swap somewhere if (i > -1) { // 3 find character at index j such that // inStr[j] = min(inStr[k]) && inStr[k] > inStr[i] for all k > i int j = i+1; int k; for(k=j;k<strSize && inStr[k];++k) { if (inStr[k] > inStr[i] && inStr[k] < inStr[j]) j = k; } // 3. Swap chars at i and j swap(&inStr[i], &inStr[j]); // 4. Sort string to the right of i qsort(inStr+i+1, strSize-i-1, sizeof(char), compare); } else { largerPermFound = 0; } }while(largerPermFound); } int main(void) { char str[] = "abc"; PrintSortedPermutations(str); return 0; }
abc acb bac bca cab cba
现场演示
std::next_permutation从<algorithm>库中为您执行此操作,只需确保首先对容器进行排序:
std::next_permutation
<algorithm>
返回值 如果函数可以将对象重新排列为字典序更大的排列,则为true。否则,该函数返回false,以指示该排列不大于前一个排列,而是可能的最小排列(按升序排列)。
如果函数可以将对象重新排列为字典序更大的排列,则为true。否则,该函数返回false,以指示该排列不大于前一个排列,而是可能的最小排列(按升序排列)。
例如:
std::string myStr = "abc"; std::stable_sort(std::begin(myStr), std::end(myStr)); do { for(auto&& element : myStr) std::cout << element << " "; std::cout << std::endl; } while (std::next_permutation(std::begin(myStr), std::end(myStr)));
输出: