johnson算法c语言,Johnson-Trotter(JT)算法生成排列

对于生成{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 需要排列的元素的范型,请务必保持范型和比较接口范型一致,否则可能产生不可预知的错误

*/

public class JTAlgorithm{

//存放排列元素的数组

protected E[] array;

//元素的方向数组

private Direction[] directions;

//比较器,用于比较元素大小

private Compare compare;

public JTAlgorithm(Class extends Compare> clazz) {

//获取比较方法的实例

this.compare = (Compare) ReflectUtils.newInstance(clazz);

}

public JTAlgorithm(Compare compare) {

//获取比较方法的实例

this.compare = compare;

}

public List generate(E[] elements) {

List result = new ArrayList();

//初始化工作

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 qk = new QuickSort(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;

}

}

PHP HMAC&lowbar;SHA1 算法 生成算法签名

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

ZeroMQ接口函数之 :zmq&lowbar;z85&lowbar;decode – 从一个用Z85算法生成的文本中解析出二进制密码

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

dfs 生成排列和组合

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

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

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

算法生成N芒星

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

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

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

C&num; 根据twitter的snowflake算法生成唯一ID

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

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

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

Prim算法生成迷宫

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

随机推荐

python 类定义 继承

0 前言 系统:win7 64bit IDE : python(x,y) 2.7.6.1 IDE集成的解释器:Python 2.7.6 (default, Nov 10 2013, 19:24:18) ...

&lbrack;解决方案&rsqb; pythonchallenge level 0

http://www.pythonchallenge.com/pc/def/0.html 问题: 2^38 >>> 2**38 >>>274877906944L 输 ...

English Audio-Books

Downloadble English Audio-Books websites 一.网站 1.可听书 2.山寨 3.有声书库 4.audioboom.com 5.豆瓣小站 6.AudioBook 二 ...

实现android apk反编译后代码混淆

通常情况下我们需要对我们开发的android代码进行混淆,以免代码在反编译时暴露敏感信息及相关技术代码: 反编译测试工具:onekey-decompile-apk-1.0.1. 在高级版本的adt创建 ...

MYSQL auto&lowbar;increment 、default 关键字

1. auto_increment: innoDB 中 表中只可以有一个列是auto_increment的,这个列还一定要是索引. create table T(X int auto_incremen ...

Android LCD&lpar;三&rpar;:Samsung LCD接口篇

关键词:android LCD控制器 Framebuffer PWM  平台信息: 内核:linux2.6/linux3.0 系统:android/android4.0  平台:samsung exy ...

java中的String类常量池详解

test1: package StringTest; public class test1 { /** * @param args */ public static void main(String[ ...

1&period;Maven的安装及配置

1 Maven 介绍 Maven这个词可以翻译为“知识的积累”,也可以翻译为“专家”或“内行”.本书将介绍Maven这一跨平台的项目管理工具.作为Apache组织中的一个颇为成功的开源项目,Maven ...

Python丨Python 性能分析大全

虽然运行速度慢是 Python 与生俱来的特点,大多数时候我们用 Python 就意味着放弃对性能的追求.但是,就算是用纯 Python 完成同一个任务,老手写出来的代码可能会比菜鸟写的代码块几倍,甚 ...

BZOJ&lowbar;1015&lowbar;&lbrack;JSOI2008&rsqb;星球大战&lowbar;并查集

BZOJ_1015_[JSOI2008]星球大战_并查集 题意:很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的 机遇,一支反抗军摧毁了帝国的超级武器, ...

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值