求数组的全排列的非递归算法

本文介绍了一种基于字典序生成全排列的方法,并通过具体示例解释了该方法的实现过程。首先找到序列中可以交换以生成下一个排列的位置,然后进行数值交换和序列反转,最终实现全排列的生成。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

求全排列一共有四种方法,字典序法,递增进位制数法,递减进位制数法,邻位对换法.我在这里讲最简单的字典序法.
这个生成法要求传进来的序列必须已经按从小到大人规律排过序.否则它不能生成正确的全排列.至于为什么用这个方法就可以生成全排列,我的知识有限,证明不了,只有拿来用了再说.
假定序列为a1,a2.... an (n > 0) ,如123456789,它从123456789开始,一直到987654321结束,中间有n个值,寻找这n个值需要做n步下面的操作:

1.找出比右边数字小的第一个数 找到这个数后,把它的位置记下来.设这个位置为pos_left;如果找不到,就说明排列完成了.
2.从右到左寻找第一个大于pos_left所在值的数,设为pos_right.
3.交换a[pos_left]与a[pos_right]的值.
4.逆转a[pos_left+1]到a[n]之间的值.
到此,寻找一个排列的步骤完成.

来个例子吧, 123, 做第1步,找到2比3小.pos_left = 2. 再做第2步,找到3比2大. pos_right = 3.然后做第3步,交换,得到 132 , 又因为pos_left后只有一个数,所以不用做逆转了.
这个太短了,干脆来个长点的 124653, 第1步找到4, pos_left = 3, 第2步找到5, pos_right = 5.然后交换得到125643, 再逆转得到125346, 从而得到新的排列.然后再对这个排列做上面4步,求出下一个排列....直到最后最后没有新排列可求出来.

java 代码
 
  1. public class Permulation {  
  2.   
  3.     /** 
  4.      * @param args 
  5.      */  
  6.     public static void main(String[] args) {  
  7.         int[] arr = { 1234 };  
  8.         do {  
  9.             for (int i = 0; i < arr.length; i++) {  
  10.                 System.out.print(arr[i] + ",");  
  11.             }  
  12.             System.out.println();  
  13.         } while (new Permulation().nextPermutation(arr));  
  14.   
  15.     }  
  16.   
  17.     public boolean nextPermutation(int[] arr) {  
  18.         int postLeft = -1;  
  19.         for (int i = arr.length - 1; i > 0; i--) {  
  20.             if (arr[i - 1] < arr[i]) {  
  21.                 postLeft = i - 1;  
  22.                 break;  
  23.             }  
  24.         }  
  25.         if (postLeft < 0) {  
  26.             return false;  
  27.         }  
  28.   
  29.         int postRight = -1;  
  30.         for (int i = arr.length - 1; i >= postLeft; i--) {  
  31.             if (arr[i] > arr[postLeft]) {  
  32.                 postRight = i;  
  33.                 break;  
  34.             }  
  35.         }  
  36.         swap(arr, postLeft, postRight);  
  37.         reverse(arr, postLeft + 1, arr.length);  
  38.         return true;  
  39.     }  
  40.   
  41.     public void swap(int[] arr, int ind1, int ind2) {  
  42.         int t = arr[ind1];  
  43.         arr[ind1] = arr[ind2];  
  44.         arr[ind2] = t;  
  45.     }  
  46.   
  47.     public void reverse(int[] arr, int ind1, int ind2) {  
  48.         for (int i = 0; i < (ind2 - ind1) / 2; i++) {  
  49.             swap(arr, ind1 + i, ind2 - 1 - (i));  
  50.         }  
  51.     }  
  52. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值