全排列问题

来源:互联网 发布:淘宝怎样装修店铺 编辑:程序博客网 时间:2024/06/11 14:11

设R={r1,r2,…,rn}是要进行排列的n个元素,R的全排列记为perm(R),Ri=R-{ri},(ri)perm(Ri)表示集合Ri的全排列中每个排列前增加一个前缀所形成的所有排列。
于是
当n=1时,perm(R)=(r),其中r是R中的唯一元素;
当n>1时,perm(R)由(r1)perm(R1), (r2)perm(R2),…,(rn)perm(Rn)构成;

求R的全排列的解决思路之一是:
- 给排列中的每个元素均赋予一个向左或向右的箭头。
- 如果元素k的箭头指向的是与其相邻但小于k的元素,则称元素k是活动的。
- 从排列 1 2 3 … n 开始,找其中的最大活动元素k,将该元素k与它所指向的相邻元素交换位置,并改变所有大于k的元素的方向。

以n=4为例,可知4的全排列数目为 4*3*2*1=24种,算法的求解过程如下图所示:

这里写图片描述

把解题思路用java语言来表示,最终的运行结果如下图所示:

这里写图片描述

这里写图片描述

首先定义一个Num类,用n个Num对象来表示1到n之间的各个数字,Num对象包含数值,方向两个属性,除了get和set四个方法外,还有用来改变方向的changeOriention()方法,代码如下:

public class Num {    private int number;    private boolean isLeft;    public Num(int number, boolean isLeft) {        this.number = number;        this.isLeft = isLeft;    }    public int getNumber() {        return number;    }    public void setNumber(int number) {        this.number = number;    }    public boolean getOrientation() {        return isLeft;    }    public void setOrientation(boolean isLeft) {        this.isLeft = isLeft;    }    public void changeOriention() {        this.isLeft = !isLeft;    }}

算法的重点在于Arrange类,Arrange类的构造函数用于完成“new一个Num类型的数组以及完成数组的初始化”

    public Arrange(int amount) {        this.amount = amount;        nums = new Num[amount];        init();    }

为每个数组元素赋予相应的数值大小以及方向,方向默认为向左

public void init() {        for (int i = 0; i < amount; i++) {            nums[i] = new Num(i + 1, true);        }    }

接下来是设计每个小步骤的算法
1 . nums[n]与其指向的元素交换位置:

public boolean swapNum(int n) {        int number = nums[n].getNumber();        boolean isLeft = nums[n].getOrientation();        if (isLeft) {            nums[n].setNumber(nums[n - 1].getNumber());            nums[n].setOrientation(nums[n - 1].getOrientation());            nums[n - 1].setNumber(number);            nums[n - 1].setOrientation(isLeft);            return true;        } else {            nums[n].setNumber(nums[n + 1].getNumber());            nums[n].setOrientation(nums[n + 1].getOrientation());            nums[n + 1].setNumber(number);            nums[n + 1].setOrientation(isLeft);            return false;        }    }

2 . 改变所有数值大于number的元素的方向:

    public void changeOrientation(int number) {        for (int i = 0; i < amount; i++) {            if (nums[i].getNumber() > number) {                nums[i].changeOriention();            }        }    }

3 . 查找最大的活动元素k:

    int[] n;    public int search() {        n = new int[amount];        for (int i = 0; i < amount; i++) {            n[i] = 0;        }        int t = 0;        for (int i = 0; i < amount; i++) {            if (nums[i].getOrientation()) {                if (i == 0) {                    continue;                }                if (nums[i - 1].getNumber() < nums[i].getNumber()) {                    n[t++] = nums[i].getNumber();                }            } else {                if (i == amount - 1) {                    continue;                }                if (nums[i + 1].getNumber() < nums[i].getNumber()) {                    n[t++] = nums[i].getNumber();                }            }        }        int k = n[0];        for (int i = 0; i < amount; i++) {            if (k < n[i]) {                k = n[i];            }        }        return k;    }

4 . 输出n的全排列结果:

int p = 0;    String str = "";    String str_num;    public String printfData() {        for (int i = 1; i <= amount; i++) {            str = str + i + " ";        }        str = str + "\n";        int h = search();        int j = 0;        while (h != 0) {            for (int i = 0; i < amount; i++) {                if (nums[i].getNumber() == h) {                    j = i;                }            }            swapNum(j);            changeOrientation(h);            for (int i = 0; i < amount; i++) {                str = str + nums[i].getNumber() + " ";            }            str = str + "\n";            p++;            h = search();        }        return "一共有" + (p + 1) + "种排列" + "\n" + str;    }

接下来只要在Frame类中添加一个TextField和一个JTextArear,TextField用来输入要获得全排列结果的元素n的大小,JTextArear用来显示全排列结果,最后在Main函数中新建一个Frame类,即可完成上述算法要求。

源代码下载地址:全排列算法

0 0