递归思想求解全排列问题:
首先说明一下全排列的含义,就是给出一组没有重复数字的数,按照有先后顺序进行排列组合,要求编程求出所有的组合。
这里用递归的思想,代码会简洁很多,关键理解一下核心代码:
swap(x[i],x[t]); //交换两数的位置。刚开始会和自己交换,自我交换就当作每处理一样。接着都是循环寻找数进行交换
prim(t+1);
swap(x[i],x[t]); //这里是回溯的时候恢复之前交换的数。
谈谈我对这里递归的理解:这里有两步交换函数的代码,第一步是交换,第二步是不断递归,第三步是递归到最后一层数位置回溯的时候,不断的恢复走过的,就是把原来交换过的数在交换回来,这里是for循环找所有的可能结果。
理解这个问题可以举个例子,就举例 1 ,2 两个数的排列组合,首先,这里是两个点,首先到点1,进入循环体中继续第一个交换函数的时候,此时先自己与自己交换,这里相当于不做处理,接着进入递归函数,来到2,由于2到末尾了,此时回溯,由于之前的交换都是自我交换,所有第二个交换函数也相当于不做处理,接着循环+1,这时候2与1 交换位置,然后接着进入递归函数,此时进入也是到末尾,看作不做处理,这时候回溯,就是吧之前恢复交换的起始状态,也就是 1, 2。此时,结束,注意每次回溯都是回到相对当前递归函数的当前原始状态。
另外一个,要较好的理解递归,可以在程序运行的结果中,就拿1开头的所有数的排列,从每个排列的最后一位往前推,可以很好的理解。
代码如下:
#include <stdio.h>
#define max 15
int a[] = {1,2,3,4};
int num = sizeof(a)/sizeof(int);
int x[max];
void swap(int &a , int &b)
{
int tem =a;
a = b;
b =tem;
}
void prim(int t)
{
if(t == num)
{
for(int i =0; i<num; i++)
printf("%d ",x[i]); //这里记录每次的数组排列的情况
printf("\n");
}
else{
for(int i =t; i<num; i++)//这一段代码是全排列的核心重点
{
swap(x[i],x[t]); //交换两数的位置。刚开始会和自己交换,自我交换就当作每处理一样。接着都是循环寻找数进行交换
prim(t+1);
swap(x[i],x[t]); //这里是回溯的时候恢复之前交换的数。
}
}
}
int main()
{
for(int i = 0; i<num; i++)
{
//x数组用来初始化存储每个城市的编号. 这里+1是为了从编号 1开始。
x[i] = i+1;
}
prim(0);
return 0;
}
程序运行如下: