/*******************************************************************************************************************************************
字典序算法如下:
设P是1~n的一个全排列:p=p1p2......pn=p1p2......pj-1pjpj+1......pk-1pkpk+1......pn
1)从排列的右端开始,找出第一个比右边数字小的数字的序号j(j从左端开始计算),即 j=max{i|pi
2)在pj的右边的数字中,找出所有比pj大的数中最小的数字pk,即 k=max{i|pi>pj}(右边的数从右至左是递增的,因此k是所有大于pj的数字中序号最大者)
3)对换pi,pk
4)再将pj+1......pk-1pkpk+1pn倒转得到排列p'=p1p2.....pj-1pjpn.....pk+1pkpk-1.....pj+1,这就是排列p的下一个下一个排列。
例如839647521是数字1~9的一个排列。从它生成下一个排列的步骤如下:
自右至左找出排列中第一个比右边数字小的数字4 839647521
在该数字后的数字中找出比4大的数中最小的一个5 839647521
将5与4交换 839657421
将7421倒转 839651247
所以839647521的下一个排列是839651247。
代码效率有待提高,586s............
********************************************************************************************************************************************/
#include <iostream>
#include <Windows.h>
using namespace std;
void swap(int &x, int & b)
{
int t;
t = x;
x = b;
b = t;
}
void inssort(int a[], int n)
{
for (int i = 1; i<n; ++i)
{
for (int j = i; (j>0) && (a[j - 1]>a[j]); --j)
{
swap(a[j], a[j - 1]);
}
}
}
int main()
{
DWORD s = GetTickCount();
{
int num[10] = { 0,1,2,3,4,5,6,7,8,9 };
int n = 9;
int time = 999999;
for (int i = 0; i < 10; ++i)
cout << num[i];
cout << endl;
while (time >0)
{
int p;
int p2;
int t[10] = { 100,100,100,100,100,100,100,100,100,100 };
for (int i = n; i > 0; --i)//取出第一次小于右边的数
{
if (num[i] > num[i - 1])
{
p = i - 1;
break;
}
}
for (int i = n; i > p; --i)
{
if (num[i]>num[p])
t[i] = num[i];
}
inssort(t, 10);//取出右边数比目标数大的数的最小值
for (int i = n; i > p; --i)
{
if (num[i] == t[0])p2 = i;
}
swap(num[p2], num[p]);//交换
p2 = n;
for (int i = p + 1; i < p2; ++i)//倒置右边的数
{
swap(num[i], num[p2]);
--p2;
}
for (int i = 0; i < 10; ++i)
cout << num[i];
cout << endl;
--time;
}
}
DWORD e = GetTickCount();
cout << "the running time is " << e - s << " ms" << endl;
system("pause");
}