#include<iostream>
#include<algorithm>#include<string.h>
/**
代码是从https://blog.youkuaiyun.com/algzjh/article/details/73456877 这里学的,还是有点懵懵的,脑子不太好使。哈哈
下面是 学习上述网址的 (非递归全排列)后自己总结的。
整体思路,就是 先保证输入的字符串顺序是 从小到大的,然后 进行全排列;
全排列 先是从 最右边往左 找到 第一个满足 左小于右 的位置;
然后从 最右边往左 找到 第一个满足 大于上面一个循环找到的位置 的元素;
然后把找到的 元素 和 第一个循环的位置对调,保证 字符串 右边变动的地方是 从右边找到的最小元素替换的,那就是字典顺序了
接着把 最右边 的元素 全部颠倒,因为 右边 应该是 从左往右 递减的。
假设 123654,那么 第一个循环 找到 3的位置,
(第二个循环)然后 我们都知道3应该和4 对换,也就是 右边那部分最小的数字3;
(两个循环分别找到要对调的元素后) 对换后,12(4)65(3)
然后 我们都知道 123654 接下去应该是 124356,保证第一个 循环找到的位置 后面一串 应该保证 从小到大
那么 最后执行 把 后面那串对调的函数,就ok了
**/
const int MAX = 10000;
char a[MAX];
int Count = 0;
using namespace std;
void LatterConvert(int former,int latter)///把后面的部分全部对调,使得后面一串也是从小到大排列
{
for(; former<latter; former++,latter--)
swap(a[former],a[latter]);
}
void QuanPaiLei(int Len)
{
int i,j;
if(Len<2)///如果长度小于2,就不需要排列了(例如只输入1一元素,“a”,那当然不用排列了)
return;
while(true)
{
cout<<"the "<<++Count<<"th permutations: "<<a<<endl;
for(i = Len-2; i>=0; i--)
{
if(a[i]<a[i+1])///从最右边往左找到第一个 满足 前小于后 的位置
break;
if(i==0) ///i = 0,说明已经一整个都是 从大到小 排序了,不需要继续循环了(例如最后一种情况654321)
return;
}
for(j =Len-1; j>i; j--) ///从最后一个位置起往左(前)找出第一个大于它的数字,然后准备调换,因为 越往左越大,所以从最右边开始找 第一个比它大的数字交换。
{
if(a[j]>a[i])///找到第一个大于 a[i]的元素位置
break;
}
swap(a[j],a[i]);
LatterConvert(i+1,Len-1);
}
}
int main()
{
while(cin >> a)
{
int Len = strlen(a);
sort(a,a+Len);
QuanPaiLei(Len);
}
return 0;
}