全排列问题
来源:互联网 发布:淘宝怎样装修店铺 编辑:程序博客网 时间: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类,即可完成上述算法要求。
源代码下载地址:全排列算法
- 全排列问题
- 全排列问题
- 字符串全排列问题
- 全排列问题
- 字符串全排列问题
- 全排列问题实现
- 全排列问题
- 全排列问题
- 递归 全排列 问题
- 全排列问题
- 全排列问题
- 全排列问题浅谈
- 全排列问题
- 全排列问题
- 全排列问题
- 全排列问题
- 全排列问题(0907)
- 全排列问题
- android-Implementing Effective Navigation,Creating Swipe Views with Tabs
- C#中DataTable排序、检索、合并等操作实例
- 编程技巧之如何让一份代码多适应底层硬件
- android 常用action和category
- Linux中Mysql的卸载方法
- 全排列问题
- 下一代超大规模软件定义网络技术实践
- PHP中ob系列函数整理
- fedora下编译运行java傻瓜入门级教程
- 网络遇到“QQ能登录但是不能打开浏览器”的问题
- nyoj--127--星际之门(一)(生成树的数量)
- PopupWindow中设置一个ListView遇到的焦点问题
- 6.Swift 中的Array
- Android之传感器(三)方向传感器