交换相邻法(2)

通过上篇文章可以看到,如果想要生成{1,2.....,n}的全排列,那么在生成的过程中我们需要将{1} {1,2} {1,2,3} ...... {1,2,3.....n}的排列进行保存。那么如何才能做到,排列覆盖当前排列而不必保留所有排列呢?

Even 给出一种描述如下:

生成{1,2,.....n}的排列算法

从1,2,3,n开始(<---  每一个数字都需要加上方向)

可移动:当数字指向方向上的相邻数字比该数字小时那么表示该数字可以移动。当然当处于集合开始,或者结尾,并且方向是向左或者向右时是不可移动的。


(1)求出最大的可移动整数m

(2)交换m和它的箭头所指的方向的与它相邻的整数

(3)交换所有满足p>m的整数p上的箭头的方向。(m经过交换后变成不可移动,然后找到次大来代替m,此时将m重新赋值,那么必然有原始的值大于当前m此整数便是p)

import java.util.Arrays;


public class DirectionSortArray {
	Number[] numbers; 
	
	public class Number{
		int index;
		int value;
		Direction direction;
	}
	enum Direction{
		left,right
	}
	public String arrayToString(Number[] numbers){
		int[] temp = new int[numbers.length];
		int i = 0;
		for(Number number : numbers){
			temp[i++] = number.value;
		}
		return Arrays.toString(temp);
	}
	public Number getBiggest(Number[] numbers){
		Number temp = null;
		for(int i = 0;i < numbers.length;i++){
			if(isMoveable(numbers[i],i,numbers) && (temp == null || temp.value < numbers[i].value)){
				temp = numbers[i];
			}
		}
		return temp;
	}
	public boolean isMoveable(Number number,int index,Number[] numbers){
		if(index == numbers.length - 1 && number.direction == Direction.right){
			return false;
		}else if(index == 0 && number.direction == Direction.left){
			return false;
		}else{
			Number nextNumber = null;
			if(number.direction == Direction.left){
				nextNumber = numbers[index - 1];
			}else{
				nextNumber = numbers[index + 1];
			}	
			if(nextNumber.value > number.value){
				return false;
			}
		}
		return true;
	}
	//进行交换
	public void swap(Number bigNumber,Number[] numbers){
		//直接进行交换
		int changedIndex = 0;
		if(bigNumber.direction == Direction.right){
			changedIndex = bigNumber.index + 1;
		}else if(bigNumber.direction == Direction.left){
			changedIndex = bigNumber.index - 1;
		}
		numbers[bigNumber.index] = numbers[changedIndex];
		numbers[bigNumber.index].index = bigNumber.index;
		numbers[changedIndex] = bigNumber;
		numbers[changedIndex].index = changedIndex;
		
		bigNumber.index = changedIndex;
		//判断当前Number是否可移动
		if(!isMoveable(bigNumber, changedIndex,numbers)){
			//不可移动时找到次大值,交换方向后,将比它大的所有数字方向进行变换
			bigNumber = getBiggest(numbers);
			if(bigNumber == null){
				return;
			}
			System.out.println(arrayToString(numbers));
			changeDirection(bigNumber,numbers);
			//进行一次交换
			swap(bigNumber,numbers);
			
		}
	}
	public void changeDirection(Number number,Number[] numbers){
		for(Number temp : numbers){
			if(temp.value > number.value){
				if(temp.direction == Direction.left){
					temp.direction = Direction.right;
				}else{
					temp.direction = Direction.left;
				}
			}
		}
	}
	//初始化数据
	public void init(){
		numbers =  new Number[4];
		for(int i = 0;i < numbers.length;i++){
			numbers[i] = new Number();
			numbers[i].direction = Direction.left;
			numbers[i].value = i + 1;
			numbers[i].index = i;
		}
	}
	//进行排序
	public void sort(){
		Number bigNumber = getBiggest(numbers);
		while(bigNumber != null){
			System.out.println(arrayToString(numbers));
			//找出最大的number
			swap(bigNumber, numbers);
			bigNumber = getBiggest(numbers);
		}
		System.out.println(arrayToString(numbers));
	}
	
	public static void main(String[] args) {
		DirectionSortArray array = new DirectionSortArray();
		array.init();
		array.sort();
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值