首先是一维数组的全排列,半个多月前在PAT上做了一个题,深有体会,可以深入理解递归这东西。
-----------------------------------------------------------------------------------------------------------------
请编写程序输出前n个正整数的全排列(n<10),并通过9个测试用例(即n从1到9)观察n逐步增大时程序的运行时间。
输入格式:
输入给出正整数n(<10)。
输出格式:
输出1到n的全排列。每种排列占一行,数字间无空格。排列的输出顺序为字典序,即序列a1,a2,⋯,an排在序列b1,b2,⋯,bn之前,如果存在k使得a1=b1,⋯,ak=bk 并且 ak+1<bk+1。
输入样例:
3
输出样例:
123
132
213
231
312
321
以下代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//指针变量相当于一个新的变量,在函数中必须建一个指针变量指向这个指针变量才能改变这个变量的值
void Print(int*a, int n) {
for (int i = 1; i <= n; i++) {
if (i == n) printf("%d\n", a[i]);
else printf("%d ", a[i]);
}
}
void perm(int*a, int*b,int n,int Index) {
if (Index== n+1) {
static int cnt = 0;
printf("第%03d次排序为:", ++cnt);
Print(a, n);
return;
}
for (int i = 1; i <= n; i++) {
if (!b[i]) {
a[Index] = i;
b[i] = 1;
perm(a, b, n, Index + 1);
b[i] = 0;
}
}
return;
}
int main() {
int n;
int a[51], b[51] = { 0 };
printf("输入n:\n");
//可最大计算出50个数的全排列
//其中a是输出数列,b是索引数列,它的索引用来锁定和输入a的数值
scanf("%d", &n);
//输入n来全排列1~n的数组
perm(a, b, n, 1);
return 0;
}
通过数组b的0,1值和递归来对数组a进行全排列的赋值
--------------------------------------------------------------------------------------------------------------------------
接下来是字符的全排列
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//全排列字符数组
void permChar(char*a,int start) {
int i;
static int cnt = 0;
if (!a[start]) {
printf("第%d次排序:", ++cnt);
for (i = 0; i < start; i++) {
printf("%c", a[i]);
}
printf("\n");
}
for (i=start; a[i]; i++) {
char temp = a[i];
a[i] = a[start];
a[start] = temp;
permChar(a, start+ 1);
temp = a[i];
a[i] = a[start];
a[start] = temp;
}
}
int main() {
char a[50] = "Miku";
permChar(a, 0);
return 0;
}
通过start索引上的字符是否为'\0'来进行判定。
--------------------------------------------------------------------------------------------------------------------
字符串数组的全排列:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//字符串二维数组的全排列(多维数组排列可据此叠加)
void swap1(char**a, char**b) {
char*temp = *a;
*a = *b;
*b = temp;
}
void swap2(char*a[],char*b[],int len) {
for (int i = 0; i < len; i++) {
swap1(a + i, b + i);
}
}//只是让其内部的字符串指针产生改变
//并不是取字符串数组的指针来改变字符串数组的位置
void permStr(char*a[][4], int length,int len,int start) {
static int cnt;
if (start == length) {
printf("\n第%d次排序:\n",++cnt);
for (int i = 0; i < length; i++) {
for (int j = 0; j < len; j++) {
printf("%s ", a[i][j]);
}
printf("\n");
}
}
for (int i = start; i < length; i++) {
swap2(a[start], a[i],len);
permStr(a, length, len, start + 1);
swap2(a[start], a[i], len);
}
}
int main() {
char*str[][4] = {
{"C","Y","F","E"},
{"cherish","you","for","ever"},
{"crying","yet","for","everything"}
};
int length = 3;
permStr(str, length, 4, 0);
}
当时试想着实现的,其实全排列模板都一样,就是二维数组在全排列的交换函数有所区别。
有利于对指针更深层次的理解:指针变量在这里相当于一个新的变量,在函数中必须建一个指针变量指向这个指针变量才能改变这个变量的值