您的位置:首页 > 其它

[续]全排列的非递归实现

2012-08-10 09:04 197 查看
      前文提到过全排列的递归实现,这里在简单的介绍下全排列的非递归实现。

       以6个数字的全排列为例说明,相当于用1,2,3,4,5,6 构造一个六位数,每一位上取一个数,这样一共有6!中方法。
很显然,这6!个数是有大小的,如果按从小到大排列,示意如下:
1 2 3 4 5 6
1 2 3 4 6 5
1 2 3 5 4 6
…………
6 5 4 3 2 1
    显然 , 每个数有唯一后继 ! 如果找到一个数没有后继(6 5 4 3 2 1),则停止。

    那么问题的重点在于如何判断是否有后继,以及怎样找到后继 ! 是否有后继很好判断,唯一没有后继的只有654321,它的特点是每位的数字比后面的大!如何找到后继,思路很清楚,即对于一个数,找到一个比它大的、最小的数!

    来考虑"926510"这个字符串,我们从后向前找第一双相邻的递增数字,"10"、"52"都是非递增的,"26 "即满足要求,称前一个数字2为替换数,替换数的下标称为替换点,再从后往前找一个比替换数大的最小数(这个数必然存在),0、1都不行,5可以,将5和2交换得到"956210",然后再将替换点后的字符串"6220"颠倒即得到"950226"。同理:比如926540的后继应该是946520,而不是956240。

[code] public class NonRecursivePermutation {


 


static int[] arr = new int[] { 1, 2, 3, 4, 5, 6};


static int count = 1;


 


// 反转区间


private static void reverse(int[] arr, int pBegin, int pEnd) {


while (pBegin < pEnd)


swap(arr, pBegin++, pEnd--);


}


 


private static void swap(int[] arr, int i, int j) {


int temp;


temp = arr[i];


arr[i] = arr[j];


arr[j] = temp;


}


 


private static boolean hasNext() {


for (int i = arr.length - 1; i > 0; i--) {


if (arr[i] > arr[i - 1])


return true;


   }


return false;


}


 


private static void next() {


int len = arr.length;


int replace = 0; // 需替换数


int firstR = 0; // 从后向前找比替换数大的第一个数


// 找降序的相邻2数,前一个数即需替换数


for (int i = len - 1; i > 0; i--) {


if (arr[i] > arr[i - 1]) {


replace = i - 1;


break;


  }


   }




//System.out.println("需替换数位置:" + replace);




// 从后向前找比替换数大的第一个数


// 比如926540的后继应该是946520,而不是956240


for (int i = len - 1; i > replace; i--) {


    if (arr[i] > arr[replace]) {


        firstR = i;


break; //找到之后直接退出


  }


   }




//System.out.println("替换数位置:" + firstR);




// replace与firstR交换


swap(arr, replace, firstR);


// 替换数后的数全部反转


reverse(arr, replace + 1, len - 1);


 


count++;


print();


}


 


private static void print() {


for (int i = 0; i < arr.length; i++)


    System.out.print(arr[i] + " ");


System.out.println();


}


 


/**


* @param args


*/


public static void main(String[] args) {


 


while (hasNext() == true) {


    next();


   }


System.out.println("数组完全反转后的结果:");


reverse(arr, 0, arr.length - 1);


print();


System.out.println("全排列的数目为:" + count);


 


/*********************/


System.out.println("数组是否存在后继:" + hasNext());


System.out.println("数组一次替换后的结果:");


next();


}


 


}

[/code]

 除了上述的找后继实现外,还有一种基于变进制数的实现。这里可以用来作为一个参考。

 最后附加利用python中itertool模块求全排列的简短代码。

import itertools
list(itertools.permutations([1,2,3]))
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: