现在的位置: 首页 > 综合 > 正文

求数组的全排列之字典序法

2013年09月11日 ⁄ 综合 ⁄ 共 2053字 ⁄ 字号 评论关闭

字典序法说明:

字典序列算法是一种非递归算法。而它正是STL中Next_permutation的实现算法。
它的整体思想是让排列成为可递推的数列,也就是说从前一状态的排列,可以推出一种新的状态,直到最终状态。比如说,最初状态是12345,最终状态是54321。

1.最初状态为12345,从最后面向前面比较,因为5>4,所以从4后面的序列中找出一个比4大,但是比在4后面的序列中最小的数,因为只有5,所有将4和5调换位置,结果为12354.

2.将原来4后面的序列进行倒置,因为现在只有1个4,倒置后还是12354.

3.已12354为基础,继续上面的步骤进行操作,下一序列的生成步骤如下:

12354(5>3) -> 12354(4,5序列中最小但是比3大的是4) -> 12453(调换4和3) -> 12435(将5,3倒置)

。。。。。。


C代码如下:

#include <stdio.h>
#include <ctype.h>
#include <malloc.h>

static void swapNum(int i, int j, int* intArray, int num);
static int getSmallestButGreatThanIndex(int* intArray, int num, int j, int i);
static void invertIntArray(int i, int* intArray, int num);
static void prtIntArray(int* intArray, int num);

int main(int argc,char* argv[]){
	int num = 0;
	int* intArray = NULL;
	int i = 0;
	int j = 0;
	
	//检查参数,必须是2个
	if(argc != 2){
		printf("there must be one parameter!\n");
		goto FINALLY;
	}
	
	//检查参数,参数必须是数字
	char* ptr = argv[1];
	while(*ptr != '\0'){
		if(isdigit(*(ptr++)) == 0){
			printf("please input a numble!\n");
			goto FINALLY;
		}
	}
	
	//将参数转换成int型
	num = atoi(argv[1]);
	intArray = (int*)malloc(sizeof(int) * num);
	//初始化数组:1,2,3,4,5,6......
	for(i=0; i<num; i++){
		intArray[i] = i+1;
	}
	
	//打印下原始数组
	printIntArray(intArray, num);
	//从数组最后面往前比较
	for(i=num-1,j=num-2; i>=1 && j>=0; i--,j--){
		//如果右边数的比左边数的大
		if(intArray[i] > intArray[j]){
			//将左边的数与右边数组中最小但是比左边的数大的数交换
			swapNum(i, j, intArray, num);
			//将左边数右边的数组序列倒置
			invertIntArray(i, intArray, num);
			//将整个数组打印
			printIntArray(intArray, num);
			//继续从数组的最后面往前面比较
			i = num;
			j = num - 1;
		}
	}
	
FINALLY:
	if(intArray != NULL){
		free(intArray);
		intArray = NULL;
		}
	return 0;
}

static void swapNum(int i, int j, int* intArray, int num){
	int swapi = getSmallestButGreatThanIndex(intArray, num, j, i);
	int temp = intArray[j];
	intArray[j] = intArray[swapi];
	intArray[swapi] = temp;
}

static int getSmallestButGreatThanIndex(int* intArray, int num, int j, int i){
	int m = 0;
	int swapi = 0;
	int smallest = num + 1;
	for(m = i; m<num; m++){
		if(intArray[m] > intArray[j] && intArray[m] < smallest){
			swapi = m;
			smallest = intArray[m];
		}
	}
	return swapi;
}

static void invertIntArray(int i, int* intArray, int num){
	int m;
	int n;
	int temp;
	for(m=i, n=num-1; (m-n)<0; m++,n--){
		temp = intArray[m];
		intArray[m] = intArray[n];
		intArray[n] = temp;
	}
}

static void printIntArray(int* intArray, int num){
	int i;
	for(i=0; i<num; i++){
		printf("%d ",intArray[i]);
	}
	printf("\n");
}


抱歉!评论已关闭.