邻位互换法—全排列

3 篇文章 0 订阅
2 篇文章 0 订阅
本文介绍了一种使用邻位互换法生成全排列的算法。通过创建初始排列,获取交换数,计算下一个排列以及从交换数还原排列,实现了全排列的遍历。算法基于Java实现,适用于组合数学和全排列问题的研究。
摘要由CSDN通过智能技术生成
package permutation;

import java.util.Scanner;

class Digit {
	int value;
	String direction;
	public Digit(){};
}

public class NeighbourExchangePermutation {

	public int factorial(int n) {
		int sum = 1;
		while (n > 1) {
			sum *= (n--);
		}
		return sum;
	}

	// get initialization permutation of scale is number
	public Digit[] creatPermutation(int number) {
		Digit[] permutation = new Digit[number];
		for (int i = 0; i < number; ++i) {
			// initialization of object
			permutation[i] = new Digit();
			permutation[i].value = i + 1;
			permutation[i].direction = "left";
		}
		return permutation;
	}					

	// get interNumber of permutation given;
	public int[] getInterNumber(Digit[] permutation) {
		// initialization for digit 2 direction is left
		String digitDirection = "left";
		int[] b = new int[permutation.length - 1];
		//find interNumber[permutation.length - 1] to interNumber[2]
		int j;
		for(int i = 0 ; i <  permutation.length - 1 ; ++ i) {
			int digit  = i + 2 ,count = 0;
			boolean flag = true;//next digit has same direction with current digit
			for(j = 0 ; j < permutation.length ; ++j) {
				if(i > 0) {
					//digit is odd then its direction decided by b[i-1]
 					if(digit % 2 == 1) {
						if(b[i - 1] % 2 == 1) digitDirection = "right";
						else digitDirection = "left";
					}
 					//digit is even then its direction decided by sum b[i-1]  with b[i-2]
 					if(digit % 2 == 0) {
 						if( (b[i - 1] + b[ i - 2]) % 2 == 1) digitDirection = "right";
						else digitDirection = "left";
 					}
				}
				if(permutation[j].value == digit) {
					if(digitDirection.endsWith("left")) {
						for(int k = permutation.length - 1 ; k > j ;-- k ) {
							if(permutation[k].value < digit) ++count;
						}
					}
					else if(digitDirection.endsWith("right")) {
						for(int k = 0 ; k < j ; ++ k) {
							if(permutation[k].value < digit) ++count;
						}
					}
					b[i] = count;break;
				}
				if(permutation[j].value == digit + 1) flag = false;
			}
			/**
			System.out.println("digit = " + digit + "\t poistion = " + j +"\t direction = " + digitDirection  );
			*/
		}
		return b;
	}

	// next interNumber
	public int[] nextInterNumber(int[] originalInterNumber) {
		for (int i = originalInterNumber.length - 1; i >= 0; --i) {
			int pow = i + 2;
			if (++originalInterNumber[i] >= pow) {
				originalInterNumber[i] -= pow;
			} else {
				return originalInterNumber;
			}
		}
		return originalInterNumber;
	}

	// get permutation via interNumebr given
	public Digit[] getPermutation(int[] b) {
		Digit[] permutation = new Digit[b.length+1];
		String direction = "";
		for(int i = 0 ; i < b.length + 1 ; ++ i) {
			permutation[i] = new Digit();
			permutation[i].value = 0;
		}
		//there are b.length+1 digit to fill the spaces
		for(int j = b.length - 1  ; j >=0  ; -- j ) {
			int digit = j + 2;
			//judge j odd or even
			if(j>=1){
				if(digit % 2 == 1){
					if(b[j-1] % 2 == 1) direction = "right";
					else direction = "left";
				}else{
					if((b[j-1] + b [j-2]) % 2 == 1) direction = "right";
					else direction = "left";
				}
			}
			if(digit == 2 ) direction = "left";
			//set the digit in right position
			int count = b[j];
			if(direction.endsWith("left")) {
				int pos = b.length +1 ;
				while( count>=0 && (--pos)>=0){
					if(permutation[pos].value == 0)--count;
					if(count < 0){
						permutation[pos].value = digit;
					}
				}
			}
			if(direction.endsWith("right")) {
				int pos = - 1 ;
				while( count>=0 && (++pos) <= b.length){
					if(permutation[pos].value == 0)--count;
					if(count < 0){
						permutation[pos].value = digit;
					}
				}
			}
		}
		int pos = -1;
		while(permutation[++pos].value!=0);
		permutation[pos].value = 1;
		return permutation;
	}

	//public
	public void neighbourExchangePermutation(Digit[] permutation){
		for(int i = 0 ; i < factorial(permutation.length);++i) {
			int[] original = getInterNumber(permutation);
			for(int j = 0 ; j < permutation.length ; ++ j){
				System.out.print(permutation[j].value);
			}
			System.out.print("\t");
			for(int k = 0 ; k < original.length ; ++ k)
				System.out.print(original[k]);
			System.out.println();
			original = nextInterNumber(original);
			permutation = getPermutation(original);
		}
	}
	// test
	public static void main(String[] args) {
		NeighbourExchangePermutation nep = new NeighbourExchangePermutation();
		
		Scanner scan = new Scanner(System.in);
		System.out.println("Please input scale of permutaion: ");
		int scale = scan.nextInt();
		nep.neighbourExchangePermutation(nep.creatPermutation(scale));
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值