字典序全排列

字典序法中,對數字一、二、3.....n的排列的前後關係是從左到右逐個比較對應的數字的前後來決定的。例如對於5個數字的排列12345和12354,排列12345在前,排列12354在後面。按照這樣的規定,5個數字的全部排列中最前面的是12345,最後面的是54321. 算法

字典序算法以下: spa

設P是1~n的一個全排列:p=p1p2......pn=p1p2......pj-1pjpj+1......pk-1pkpk+1......pn 3d

1)從排列的右端開始,找出第一個比右邊數字小的數字的序號j(j從左端開始計算),即j=max{i|pi<pi+1} code

2)在pj的右邊數字中,找到全部比pj大的數字中最小的數字pk 排序

3)對換pjpk input

4)再將pj+1....pk-1pkpk+1pn逆轉獲得排列p'=p1p2...pj-1pjpn...pk+1pkpk-1...pj+1,這就是排列p的下一個排列。 io

例如21379854是數字1~9的一個排列。從它生成下一個排列的步驟以下: class

1)「自右至左」找出排列中第一個比右邊數字小的數字:7 循環

2)在該數字後的數字中找到比7大的數中最小的一個:8 sort

3)將7和8交換:21389754

4)將9754逆轉:21384579

因此21379854的下一個排列是21384579

#include <stdio.h>

int a[10],N;

int cmp(const void *a,const void *b)
{
	return *(int*)a-*(int*)b;
}
int fac();
void Fun();
void Reverse(int m,int n);
void Output();

int main()
{
	int i;
	while (printf("\nPlease input N:  "),scanf("%d",&N)!=EOF)
	{
		printf("Please input %d numbers:\n",N);
		for (i=0;i<N;i++)
		{
			scanf("%d",&a[i]);
		}
		qsort(a,N,sizeof(a[0]),cmp);  //先將N個數排序
		printf("These numbers are:  \n");
		for (i=0;i<N;i++)
		{
			printf("%3d",a[i]);
		}
		printf("\n");
		Fun();
	}
	return 0;
}

int fac()  //求N的階乘,即全排列的個數
{
	int count=1,i=2;
	while (i<=N)
	{
		count*=i;
		i++;
	}
	return count;
}

void Fun()
{
	int index1,index2,i,k,min,n,temp;  //index1爲上述j下標,index2爲上述k下標
	n=fac();

	for (k=1;k<n;k++)    //n次循環
	{
		for (index1=N-2;index1>=0;index1--)    //求index1下標
		{
			if (a[index1]<a[index1+1])
			{
				break;
			}
		}

		min=32767;
		for (i=index1+1;i<N;i++)  //求index2
		{
			if (a[i]>a[index1])
			{
				if (a[i]<min)
				{
					min=a[i];
					index2=i;
				}
			}
		}
		temp=a[index1];       //交換a[index1],a[index2]
		a[index1]=a[index2];
		a[index2]=temp;

		Reverse(index1+1,N-1); //逆置a[index1]到a[N-1]的數
		Output();  //輸出
	} 
}

void Reverse(int m,int n)
{
	int temp;
	while (m<n)
	{
		temp=a[m];
		a[m]=a[n];
		a[n]=temp;
		m++;
		n--;
	}
}

void Output()
{
	int i;
	for (i=0;i<N;i++)
	{
		printf("%3d",a[i]);
	}
	printf("\n");
}
相關文章
相關標籤/搜索