全排列呢就是我们在数学中学的将一组数字或者是字母的所有排列方式计算出来的数学工具。
比如,ABCD这四个字母随机取三个字母的全排列就有24种之多。那么,我们如何用程序来实现他呢?
我们来探讨一下这个问题的手工过程:
无非就是在取当前字母时看当前字母是否可取,如果不可取则看下一个,如果可取就将该字母取出。
这就很符合递归的特性,我们每次只关心当前字母是否可取即可。
我们可以给一个下标数组,下标数组的初值全部赋值为0,下标数组的长度与输入的字符串的长度相同。当字符串中的某一个字符被选中,则该字符在下标数组中对应的值改为1。并且将这个字符存入我们最后要输出的字符串数组中,当最后的字符串数组存够三个字符后,我们让它输出即可,这也是递归停止的条件。
代码如下:
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include "tool.h"
#define targetCount 3
boolean isSafe(int *arr, int index);
void completeArrangement(int *arr, int index, char *str, char *target, int temp);
void completeArrangement(int *arr, int index, char *str ,char *target, int temp) {
int i;
if (temp == 3) {
printf("%s\n",target);
return;
}
for (i = 0; i < strlen(str); i++) {
if (isSafe(arr,i)) {
arr[i] = 1;
target[temp] = str[i];
completeArrangement(arr, index+1, str , target, temp+1);
arr[i] = 0;
}
}
}
boolean isSafe(int *arr, int index) {
if (arr[index] == 1) {
return FALSE;
} else {
return TRUE;
}
}
int main() {
char str[5];
int length;
int *arr = NULL;
int temp = 0;
char target[targetCount];
printf("please input your string:");
gets(str);
length = strlen(str);
arr = (int *) calloc(sizeof(int),length);
completeArrangement(arr, 0, str , target, temp);
free(arr);
return 0;
}
#ifndef _TOOL_H_
#define _TOOL_H_
typedef unsigned char boolean;
#define TRUE 1
#define FALSE 0
#define NOT_FOUND -1
#endif
关于递归:
很多人觉得递归很高大上,很难,其实递归就是对一个方法的反复调用,在编写递归程序时不要想的太多,考虑的越简单越纯粹越好,而且在编写递归时不要一上手就是编写最核心的部分,相反,编写递归程序时一定要对递归的结束条件十分清楚,不然很容易在程序运行时造成系统堆栈溢出。
写的不好,还请大神下面指正。