对于生成{1,……,n}的所有n!个排列的问题,我们可以利用减治法,该问题的规模减一就是要生成所有(n-1)!个排列。假设这个小问题已经解决了,我们可以把n插入到n-1个元素的每一种排列中的n可能的位置中去,来得到较大规模大问题的一个解。按照这种方式生成的所有排列都是独一无二的,并且他们的总数应该是n(n-1)!=n!。这样,我们都得到了{1,……,n}的所有排列。
    JohnsonTrotter算法实现形式。
    JohnsonTrotter(n)
        输入:一个正整数n
        输出:{1,……,n}的素有排列的列表
        将第一个排列初始化为方向向左的元素数组
        while 存在一个移动元素k do
            求最大的移动元素k
            把k和它箭头指向的相邻元素互换
            调转所有大于k的元素的方向
            将新排列添加到列表
(摘自算法设计与分析基础)
 
    下午自己实现了一下这个算法,将其改成可以把N个不重复的元素排列出来,程序中使用到的比较器提供接口需要自己去实现,程序运行需要把使用者自己实现的比较器注入程序。自我感觉程序灵活性还可以。
/**
* 使用JT算法进行排列组合。
* 注意:请务必保持范型和比较接口范型一致,否则可能产生不可预知的错误
* @author LiuYeFeng<897908343@qq.com>
* @date 2015年4月9日 下午5:31:00
* @CopyRight 2015 TopView Inc
* @version V1.0
* @param <E> 需要排列的元素的范型,请务必保持范型和比较接口范型一致,否则可能产生不可预知的错误
*/
public class JTAlgorithm<E>{ //存放排列元素的数组
protected E[] array;
//元素的方向数组
private Direction[] directions;
//比较器,用于比较元素大小
private Compare<E> compare; public JTAlgorithm(Class<? extends Compare<E>> clazz) {
//获取比较方法的实例
this.compare = (Compare) ReflectUtils.newInstance(clazz);
} public JTAlgorithm(Compare<E> compare) {
//获取比较方法的实例
this.compare = compare;
}

public List<E[]> generate(E[] elements) {
List<E[]> result = new ArrayList<E[]>(); //初始化工作
init(elements); //最大可移动元素的位置
int biggestFlag = findBiggestMobileElement();
//自身也为一种排列
result.add(Arrays.copyOf(array, array.length)); //存在可移动最大元素k
while (biggestFlag != -1) {
//将k和箭头指向的相邻元素互换
biggestFlag = changeBiggestElementAndNeighbor(biggestFlag);
//调转所有大于k的元素的方向
changeDirection(biggestFlag);
//将新排列添加到结果集
result.add(Arrays.copyOf(array, array.length));
//重新查找可移动最大元素
biggestFlag = findBiggestMobileElement();
} return result;
}


private void init(E[] elements) {
//用快排把元素排序
QuickSort<E> qk = new QuickSort<E>(compare);
qk.sort(elements, 0, elements.length - 1); array = elements;
directions = new Direction[array.length]; //初始化方向
for (int i = 0; i < directions.length; i++) {
directions[i] = Direction.LEFT;
}
}


/**
* 把比loc位置大的元素的方向反转
* @param loc
*/
private void changeDirection(int loc) {
for (int i = 0; i < array.length; i++) {
if (compare.greaterThan(array[i], array[loc])) {
directions[i] = (directions[i] == Direction.LEFT) ? Direction.RIGHT : Direction.LEFT;
}
}
}


/**
* 把loc元素和它的邻居互换,并把互换后loc的新位置返回
* @param loc
* @return loc的新位置
*/
private int changeBiggestElementAndNeighbor(int loc) {
int neighbor = -1; if (directions[loc] == Direction.LEFT) {
neighbor = loc - 1;
} else {
neighbor = loc + 1;
} E temp = array[loc];
array[loc] = array[neighbor];
array[neighbor] = temp; Direction dTemp = directions[loc];
directions[loc] = directions[neighbor];
directions[neighbor] = dTemp; return neighbor;
}


/**
* 查找最大可移动元素
* @return 最大可移动元素的位置
*/
private int findBiggestMobileElement() {
int loc = -1;
int biggestLoc = -1; for (int i = 0; i < array.length; i++) {
//判断左右方向
if (directions[i] == Direction.LEFT) {
//如果是头元素,则无法向左比较,跳过
if (i == 0) {
continue;
} if (compare.greaterThan(array[i], array[i - 1])) {
loc = i;
}
} else {
//如果是尾元素,则无法向右比较,跳过
if (i == array.length - 1) {
continue;
} if (compare.greaterThan(array[i], array[i + 1])) {
loc = i;
}
} //如果第一次找到可移动元素,则把最大可移动元素改变,之后把本次找到的可移动元素和最大可移动元素进行比较
if (loc != -1 && biggestLoc == -1) {
biggestLoc = loc;
}else if (biggestLoc != -1 && compare.greaterThan(array[loc], array[biggestLoc])) {
biggestLoc = loc;
}
} return biggestLoc;
}
}

Johnson-Trotter(JT)算法生成排列的更多相关文章

  1. PHP HMAC_SHA1 算法 生成算法签名

    HMAC_SHA1(Hashed Message Authentication Code, Secure Hash Algorithm)是一种安全的基于加密hash函数和共享密钥的消息认证协议. 它可 ...

  2. ZeroMQ接口函数之 :zmq_z85_decode – 从一个用Z85算法生成的文本中解析出二进制密码

    ZeroMQ 官方地址 :http://api.zeromq.org/4-0:zmq_z85_decode zmq_z85_decode(3)         ØMQ Manual - ØMQ/4.1 ...

  3. dfs 生成排列和组合

    利用深度优先搜索的性质可以方便的生成n的排列和组合,但是生成组合时每个组合里面元素的个数必须事先确定,以前以为生成组合跟排列一样到n时就可以回溯,直到今天做了某题之后才发现那是错的,那样做生成不了所有 ...

  4. 根据twitter的snowflake算法生成唯一ID

    C#版本 /// <summary> /// 根据twitter的snowflake算法生成唯一ID /// snowflake算法 64 位 /// 0---0000000000 000 ...

  5. 算法生成N芒星

    前面两个图像生成算法是:道教的太极八卦图和佛教的卐和卍字图.这一节整个洋气的图像:芒星.但愿我别召唤出什么恐怖的禁忌,尤其今晚还是万圣节之夜.平时看玄幻小说,经常读到有关六芒星,七芒星,九芒星的技法. ...

  6. 在 iPad 上试验从用算法生成法线贴图-到法线映射光照效果

    在 iPad 上试验从用算法生成法线贴图-到法线映射光照效果 目录 概述 一般来说, 法线贴图是用高模的法线图, 低模的纹理图, 来生成较好的渲染效果. 而法线图通常是通过图像处理软件来生成的, 这里 ...

  7. C# 根据twitter的snowflake算法生成唯一ID

    C# 版算法: using System; using System.Collections.Generic; using System.Linq; using System.Text; using ...

  8. 蓝桥杯--算法提高 排列数 (简单dfs)

    算法提高 排列数   时间限制:1.0s   内存限制:256.0MB      问题描述 0.1.2三个数字的全排列有六种,按照字母序排列如下: 012.021.102.120.201.210 输入 ...

  9. Prim算法生成迷宫

    初始化地图 function initMaze(r,c){ let row = new Array(2 * r + 1) for(let i = 0; i < row.length; i++){ ...

随机推荐

  1. TD-LTE华为 DBS3900数据配置实践 典型案例

    案例:华为 DBS3900 双基站二扇区配置(同频切换) 一.数据配置前的硬件准备: HW-DBS3900: (1#基站名称) FAN (风扇),安装在 16#槽位: LBBP (基带处理单板),安装 ...

  2. 【Elasticsearch学习】文档搜索全过程

    在ES执行分布式搜索时,分布式搜索操作需要分散到所有相关分片,若一个索引有3个主分片,每个主分片有一个副本分片,那么搜索请求会在这6个分片中随机选择3个分片,这3个分片有可能是主分片也可能是副本分片, ...

  3. R语言:计算现金工资的币数

    新入职的员工,有的没有相应银行卡,需要计算现金工资的币数.实发工资,一般取整数. 简化计算,纸币面值只有100.10.1.4278除以100等于42余78,78除以10等于7余8,8除以1等于8. 复 ...

  4. search(12)- elastic4s-聚合=桶+度量

    这篇我们介绍一下ES的聚合功能(aggregation).聚合是把索引数据可视化处理成可读有用数据的主要工具.聚合由bucket桶和metrics度量两部分组成. 所谓bucket就是SQL的GROU ...

  5. 第一行Kotlin系列(三)Intent 向上一页返回数据onActivityResult的使用

    1.MainActivity.kt跳转处理 声明全局的按钮对象 private lateinit var button8: Button 实例化按钮对象 button8 = findViewById( ...

  6. Netty 中的粘包和拆包

    Netty 底层是基于 TCP 协议来处理网络数据传输.我们知道 TCP 协议是面向字节流的协议,数据像流水一样在网络中传输那何来 "包" 的概念呢? TCP是四层协议不负责数据逻 ...

  7. 设计模式系列之适配器模式(Adapter Pattern)——不兼容结构的协调

    模式概述 模式定义 模式结构图 模式伪代码 类适配器,双向适配器,缺省适配器 类适配器 双向适配器 缺省适配器 模式应用 模式在JDK中的应用 模式在开源项目中的应用 模式总结 主要优点 主要缺点 适 ...

  8. equals(), "== ",hashcode() 详细解释

    Object 通用方法容易混淆的定义 先搞清楚各自的定义 "==" 用来判断 相等 equals() 用来判断 等价 hashcode() 用来返回散列值 "==&quo ...

  9. 聊聊Grpc使用中的坑以及怎么填

    总所周知,随着云技术的发展,和业务的复杂度的上升,越来越多的系统开始拆分成独立的子模块微服务.模块之间免不了相互通信.但是随着业务量的增多,传输量也随之增大,偶发性timeout,无响应, 传输量过大 ...

  10. jsp循环map map的key值不固定

    <c:if test="${not empty parammap}"> <c:forEach items="${parammap }" var ...