Johnson-Trotter(JT)算法求全排列

Johnson-Trotter算法描述

算法  JohnsonTrotter(n)

   //实现用来生成排序的 Johnson-Trotter 算法

   //输入:正整数n(代表序列1,2,···,n)

   //输出:{1,2,···,n}的全排列

   将第一个全排列初始化为

   while  存在一个移动元素 do

    求最大的移动元素 k

    把 k 和它箭头指向的相邻元素互换

    调转所有大于 k 的元素的方向

    将新排列添加到排列中

以 n=3 为例

下面我将贴出Johnson-Trotter算法的JAVA代码

  1 package JT;
  2 
  3 import java.util.Scanner;
  4 
  5 public class Johnson_Trotter {
  6     //求最大的移动元素
  7     public static int maxk(int n, int[] array, boolean[] f) {
  8         //k存储最大移动元素的下标
  9         int k = -1, max = 0;
 10         for(int i = 0; i < n; i++) {
 11             //当前元素的方向是左边,则与左边的元素比较看是否可以移动
 12             //若可移动则与当前可移动最大值比较
 13             if(f[i] == false) {
 14                 if(i > 0 && array[i] > array[i - 1] && array[i] > max) {
 15                     k = i;
 16                     max = array[i];
 17                 }
 18             }
 19             //右边
 20             else {
 21                 if(i < n - 1 && array[i] >array[i + 1] && array[i] > max) {
 22                     k = i;
 23                     max = array[i];
 24                 }
 25             }
 26         }
 27         return k;
 28     }
 29     //元素和方向的交换
 30     public static int[] swap2(int[] array, boolean[] f, int i, int j) {
 31         int temp = array[i];
 32         array[i] = array[j];
 33         array[j] = temp;
 34         boolean temp1 = f[i];
 35         f[i] = f[j];
 36         f[j] = temp1;
 37         return array;
 38     }
 39     //调转方向
 40     public static boolean[] Reverseid(int[] array, int k, boolean[] f) {
 41         for(int i = 0; i < array.length; i++) {
 42             if(array[i] > array[k]) {
 43                 f[i] = f[i] ? false : true;
 44             }
 45         }
 46         return f;
 47     }
 48 
 49     public static void Jt(int n) {
 50         //方向数组,false为左,true为右
 51         boolean[] flag = new boolean[n];
 52         //数字数组
 53         int[] idata = new int[n];
 54         //k为当前可移动元素的最大值
 55         int k = 0;
 56         //初始化两个数组
 57         for(int i = 0; i < n; i++) {
 58             idata[i] = i + 1;
 59             flag[i] = false;
 60         }
 61         //输出第一个初始化的排列,此排列不会自动生成
 62         for(int i = 0; i < n; i++) {
 63             System.out.print(idata[i]);
 64             System.out.print(flag[i]);
 65         }
 66         System.out.println();
 67         //初始化k,获取第一个可移动的最大元素
 68         k = maxk(n, idata, flag);
 69         //循环直到没有可移动的元素
 70         while(k != -1) {
 71             //可向右移动
 72             if(flag[k]) {
 73                 //移动时,将元素和方向都交换
 74                 idata = swap2(idata, flag, k, k + 1);
 75                 //此时k所在的元素已经向右交换,k也需要对应加1
 76                 k++;
 77             }
 78             //可向左移动
 79             else {
 80                 idata = swap2(idata, flag, k, k - 1);
 81                 k--;
 82             }
 83             flag = Reverseid(idata, k, flag);//调转所有大于k的元素的方向
 84             //输出当前的一个排列
 85             for(int i = 0; i < n; i++) {
 86                 System.out.print(idata[i]);
 87                 System.out.print(flag[i]);
 88             }
 89             System.out.println();
 90             k = maxk(n, idata, flag);//获取下一个k
 91         }
 92     }
 93 
 94     public static void main(String[] args) {
 95         Scanner scan = new Scanner(System.in);
 96         int n = scan.nextInt();//输入n
 97         Jt(n);//调用算法
 98         scan.close();
 99     }
100 }

代码运行结果如下:(带有元素方向)

Please put in n :4
1false2false3false4false
1false2false4false3false
1false4false2false3false
4false1false2false3false
4true1false3false2false
1false4true3false2false
1false3false4true2false
1false3false2false4true
3false1false2false4false
3false1false4false2false
3false4false1false2false
4false3false1false2false
4true3true2false1false
3true4true2false1false
3true2false4true1false
3true2false1false4true
2false3true1false4false
2false3true4false1false
2false4false3true1false
4false2false3true1false
4true2false1false3true
2false4true1false3true
2false1false4true3true
2false1false3true4true

Process finished with exit code 0

 此文章为原创,转载需说明出处。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值