题目类似剑指offer的第28题,这里在粘贴一下:题目:输入一个字符串,打印出该字符串中字符放入所有排列。例如输入字符串abc,则打印出字符a、b、c所能排列出来的所有字符串abc、acb、bac、bca、cab和cba。
递归的实现算法:http://blog.csdn.net/moses1213/article/details/51055692
这里用非递归的算法实现:
假设有字符串p1 p2…pj-1pj pj+1…pk-1 pk pk+1…pn ,对字符串进行快速排序,得到所有排列中的最小值,然后寻找下一个排列,下一个排列比当前值大,而且是所有排列中比当前值大的最小排列。直到排列已是最大值,不再寻找下一个排列,此时从最小到最大全部实现,即为字符串的全排列。下面是下一个排列的算法步骤:
(1)从排列的尾部(最右边)开始, 找出第一个比右边相邻数字小的索引j ( j 从首部开始计算), 即j = max{i | pi < pi+1};
(2)在pj 右边的数字中, 找出所有比pj 大的数字中最小的数字的索引k, 即k= max{i | pi > pj};由于pj 右边的数字是从右至左递增的, 因此k 是所有大于pj 的数字中索引最大的;
(3) 交换pj 与pk;
(4) 将pj+1...pk-1, pj, pk+1...pn 翻转得到p的下一个排列p′
算法的证明见:http://www.doc88.com/p-6438124960748.html
#include <iostream> #include <cstring> using namespace std; void Swap(char* a, char* b) { char temp = *a; *a = *b; *b = temp; } void Reverse(char* p1, char* p2) { while(p1 < p2) Swap(p1++, p2--); } //非递归版本实现 bool NextPermutation(char* pStr) { char* pEnd = pStr + strlen(pStr) - 1; char* pSwap = pEnd; char* index; //寻找替换数 for(index = pEnd - 1; index >= pStr; --index) { if(*index < *(index + 1)) { pSwap = index; break; } } //pSwap没更新,即不存在这样的替换数,表明已是最大值 if(pSwap == pEnd) <span style="white-space:pre"> </span>return false; //寻找比*pSwap大的最小数 char* pMinLarger = pSwap + 1; for(index = pMinLarger + 1; index <= pEnd; ++index) { if(*index > *pSwap && *index <= *pMinLarger) pMinLarger = index; } Swap(pSwap, pMinLarger); Reverse(pSwap + 1, pEnd); return true; } int cmp(const void *a,const void *b) { return int(*(char *)a - *(char *)b); } int main(void) { char str[] = "13223"; qsort(str , strlen(str),sizeof(char),cmp); do cout << str << endl; while(NextPermutation(str)); return 0; }