1. 程式人生 > >字典序輸出全排列演算法

字典序輸出全排列演算法

					#include<stdio.h>
					#include<iostream>  
					using namespace std;   
					void pailie(int a[],int n);
					main()
					{
						int n;
						scanf("%d",&n);
						int a[n],i;
						for(i=1;i<=n;i++)      //必須保證傳入到函式中的一組數一定要已經是按從小到大排列好的,否則整個演算法就會崩潰 
						a[i-1]=i;
						pailie(a,n);
						return 0;
					}
					void pailie(int a[],int n)
					{
						 int i;
						 int j, k;  
						 while (1)  
					    {  
					       	for(i=0;i<n;i++)
						    printf("%d",a[i]);  //當第一次進入迴圈時,就會輸出一次從一開始就從小到大排列好的數 
					  		printf("\n");
/*這裡的j>=0要放在前面*/    for (j = n - 2; j >= 0 && a[j] > a[j + 1]; j--);  //這一步是從這一組數中右邊(即從倒數第二個數判斷,因為倒數第一個數右邊沒有數字)開始判斷,找出第一個比自己右邊數字小的數,下標存到j中 
  
					        if (j < 0) return;  //當已經找不到還有比自己右邊數字大的時候,就說明所有的全排列已經全部輸出了。因為字典序全排列就是從一個最小的數,一直到最大的數1234----4321,當輸到最大時,全排列就全部輸出了 
					          
					        for (k = n - 1; k > j&&a[k] < a[j]; k--);   // 這一步是從這一組數中最右邊開始判斷的,在上一步找出j那個位置的數的右邊的數字中,找出所有比j大的數中最小的數字,把他的下標存入k中,用來在下一步將j和k的值互換(右邊的數從右至左是遞增的,因此k是所有大於j的數字中序號最大者) 
					  
					        swap(a[k], a[j]);  //這是將上面找到第一個比左邊數字小的數字j和數字j右邊比j大的數字中最小的數字k互換一下,這是為了把還沒排在前面過的數字,排到前面去 
					  
					        for (int l = j + 1, r = n - 1; l < r; l++, r--)  //因為此時j這個位置的數字後面的數是從大到小排序的,給對調一下就得出了下一次要輸出的全排列 
					            swap(a[l], a[r]);  
					    }  
					}