全排列演算法的思想和C語言的程式碼實現
1、根本思想:遞迴
2、舉例設R={3,5,8,2}為需要排列的元素集合,{3,5,8,2}的全排列=3後面跟著{5,8,2}的全排列+5後面跟著{3,8,2}的全排列+8後面跟著{3,5,2}的全排列+2後面跟著{3,5,8}的全排列。對於{5,8,2}的全排列=5後面跟著{8,2}的全排列+8後面跟著{5,2}的全排列+2後面跟著{5,8}的全排列。以此類推,直到到排列只剩下一個元素。
二、程式碼實現
#include <stdio.h>
int n = 0; //n用來計全排列的總數
int main() //主函式
{ int list[] = {3,5,8,2};
perm(list, 0, 3);
printf("total:%d\n", n); //輸出n的個數
}
void perm(int list[], int begin, int end) //產生list[begin:end]的所有排列
{
int i;
if (begin == end) //begin等於end,即list中只有一個元素時
{
for(i = 0; i <= begin; i++)
printf("%d ", list[i]); //打印出這個排列
printf("\n");
n++; //n的個數加一,表示又有一種情況產生了
}
else
{
for(i = begin; i <= end; i++) //還有多個元素待排列,依次產生:3後面跟著{5,8,2}的全排列+5後面跟著{3,8,2}的全排列+8後面跟著{3,5,2}的全排列+2後面跟著{3,5,8}的全排列
{
swap(&list[begin], &list[i]);
perm(list, begin + 1, end);
swap(&list[begin], &list[i]);
}
}
}
void swap(int *a, int *b) //用來交換兩個變數值的函式
{
int m;
m = *a;
*a = *b;
*b = m;
}
三、程式碼解釋補充
1、 對於
for(i = begin; i <= end; i++)
{
swap(&list[begin], &list[i]);
perm(list, begin + 1, end);
swap(&list[begin], &list[i]);
}
每次都會先將整組數中的所有的數分別與第一個數交換,這樣就總是在處理後n-1個數的全排列。
2、在permut函式for迴圈中,呼叫完permut之後還要執行一次swap的,要把陣列還原成未呼叫permut之前的狀態,保證下一次迴圈或者上一級迴圈swap陣列元素的正確。