1. 程式人生 > >C語言 全排列的實現

C語言 全排列的實現

首先是一維陣列的全排列,半個多月前在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);
}

當時試想著實現的,其實全排列模板都一樣,就是二維陣列在全排列的交換函式有所區別。

有利於對指標更深層次的理解:指標變數在這裡相當於一個新的變數,在函式中必須建一個指標變數指向這個指標變數才能改變這個變數的值