1.计算list[1,2,3]的全排列
2.代码
#include <stdio.h>
#include <stdlib.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
void swap(int *a,int *b){
int temp = *a;
*a = *b;
*b = temp;
}
int perm(int list[],int k, int m){
int i;
if(k==m){
for(i=0;i<m;i++)
printf("%d",list[i]);
printf("\n");
}else{
for(i=k;i<m;i++){
swap(&list[k],&list[i]);
perm(list,k+1,m);
swap(&list[k],&list[i]);
}
}
}
int main(){
int n;
int arr[]={1,2,3};
n = sizeof(arr)/sizeof(arr[0]);
perm(arr,0,n);
}
3.代码理解
(1)定义swap
交换函数。
(2)定义全排列的运算逻辑(perm
函数)。
(3)应用实例计算结果(main
函数)。
以下是每个步骤的作用和算法的总体思路:
第一步:定义swap
交换函数
void swap(int *a,int *b){
int temp = *a;
*a = *b;
*b = temp;
}
这个swap
函数的作用是对两个整数进行交换。函数通过指针参数a
和b
接收要交换的两个整数的地址,然后利用一个临时变量temp
来辅助完成交换。这样,调用swap
函数后,传入的两个整数在内存中的值就被交换了。
第二步:定义全排列的运算逻辑(perm
函数)
int perm(int list[],int k, int m){
int i;
if(k==m){
for(i=0;i<m;i++)
printf("%d",list[i]);
printf("\n");
}else{
for(i=k;i<m;i++){
swap(&list[k],&list[i]);
perm(list,k+1,m);
swap(&list[k],&list[i]);
}
}
}
perm
函数是全排列算法的核心。它采用递归的方式来生成数组list
从索引k
到m-1
的所有排列。
(k是定义坐标索引位置,m是列表长度)
- 当
k
等于m
时,说明已经遍历到了数组的末尾,此时打印出当前的一个排列。 - 否则,从
k
到m-1
的每一个位置i
,都执行以下操作:- 交换
list[k]
和list[i]
。 - 递归调用
perm
函数,以生成从k+1
到m-1
的排列。 - 回溯:再次交换
list[k]
和list[i]
,以撤销之前的交换操作,保证下一次循环时数组状态正确。(
- 交换
这种递归和回溯的方式确保了每个元素都有机会被放在每个位置,从而生成所有可能的排列。
第三步:应用实例计算结果(main
函数)
在main
函数中,首先定义了一个整数数组arr
,并计算了数组的长度n
。然后调用perm
函数,以arr
为参数,从索引0
开始生成全排列。这样,程序的输出就是数组arr
的所有可能排列。
4.总体思路
全排列算法的核心在于递归和回溯。通过递归,算法可以逐步深入到数组的每一个位置;通过回溯,算法可以在生成一个排列后返回到上一个位置,继续生成其他的排列。这种递归和回溯的方式保证了算法能够生成所有可能的排列,而不会遗漏或重复。
此外,需要注意的是,全排列算法的时间复杂度是O(n!),其中n是数组的长度。这是因为对于每个位置,都有n-k种选择(k是当前递归层级的起始位置),所以总的排列数是n的阶乘。因此,当数组长度较大时,全排列算法的运行时间可能会很长。