Non-recursive full permutation python implementation

python algorithm

Permutation


排列(英语:Permutation)是将相异物件或符号根据确定的顺序重排。每个顺序都称作一个排列。例如,从一到六的数字有720种排列,对应于由这些数字组成的所有不重复亦不阙漏的序列,例如4, 5, 6, 1, 2, 3 与1, 3, 5, 2, 4, 6。【From Wikipedia】
从n个相异元素中取出 k个元素,k个元素的排列数量为:

\[ {P_{k}^{n}={\frac {n!}{(n-k)!}}} \]

其中P意为Permutation(排列),!表示阶乘运算。全排列而取k为n,则结果为n!。

Full permutation generation algorithm

  1. lexicographical order

    The lexicographical order is to arrange the elements in lexicographical order (az, 1-9). Using the order of the dictionary as the basis for comparison, the size of the two strings can be compared. For example, "1" < "13"<"14"<"153" is the result of comparing each digit one by one. For a string "123456789", it can be known that the smallest string is "123456789", and the largest string is "987654321". In this way, the full permutation is generated by the lexicographical method for this string, which is to generate a string such as "123456789"->"123456798"->......->"987654312"->"987654321" in turn. The lexicographical method requires that this one and the next have the longest possible common prefix, that is, changes are limited to the shortest possible suffix.

  2. vicinal swap method

    The algorithm was first proposed by Johnson-Trotter, and it is an algorithm that can quickly generate full permutations. Its next full permutation is always obtained by exchanging some adjacent two bits of the previous full permutation. If the arrangement of n-1 elements is known, and n is inserted into different positions of the arrangement, the arrangement of n elements is obtained. Arbitrary permutations of n elements can be generated in this way. This approach has one drawback: to generate an n-element permutation, we must know and store all n-1-element permutations before we can generate all n-order permutations.
  3. Incremental carry method

    The algorithm is based on a sequence of incrementing base numbers [3]. Incremental base number means that the base of the number increases as the number of digits increases. Under normal circumstances, the base of the rightmost number is 2, the base of the second right is 3, and so on. The n-digit incrementing base number contains n! digits in total, so it can be combined with the full permutation generation algorithm.
  4. Decrementing carry method

This method is similar to the principle of the incremental carry system, the difference is that the "decrementing carry system" defined by it is that the base of the number decreases as the number of digits increases. In this system, the leftmost base is generally 2, and the second left base is 3. The rest of the principle is basically the same as the incremental carry method.
---
###Python implementation

#####lexicographical method
###### non-recursive algorithm

设P是集合{1,2,……n-1,n}的一个全排列:P=P1P2……Pj-1PjPj+1……Pn(1≤P1,P2,……,Pn≤n-1)
1.从排列的右端开始,找出第一个比右边数字小的数字的序号j,即j=max{i|Pi&lt;Pi+1,i>j}在Pj的右边的数字中,
找出所有比Pj大的数字中最小的数字Pk,即k=min{i|Pi>Pj,i>j}
2.交换Pi,Pk

3. Reverse the descending part Pj+1Pj+2...Pn at the right end of the arrangement, because the numbers at the right end of j are in descending order, so only the left and right sides need to be exchanged until the middle, so a new arrangement P'= P1P2……Pj-1PkPn……Pj+2Pj+1
###### Code

#!/usr/bin/env python2
# -*- coding: utf-8 -*-
"""
@author: gsharp
"""
def Swap(n,a,b):
    n[a],n[b] = n[b],n[a]
    return None
def Reverse(n,begin):
    if len(n) > begin:
        i = begin
        j = len(n)-1
        while i < j:
            Swap(n,i,j)
            i += 1
            j -= 1
    return n

def FindMin(n,i):
    j = len(n)-1
    k = i + 1
    while j > i:
        if n[j] > n[i] and n[j] < n[k]:
            k = j
        j -= 1
    return k

def Permut(n):
    count = 0
    j = len(n) -1  
    if j < 1:
        return n
    else :
        print n
        count += 1
        while j >= 1:
            i = j - 1
            if n[i] < n [j] :
                k = FindMin(n,i)
                Swap (n,i,k)
                Reverse (n,j)
                j = len(n) - 1
                count += 1
                print n
            else :
                j -= 1
    print count

n =[1,2,3,4,5,6]
Permut(n)

Notice:

  1. Here only lists with comparable values ​​can be sorted, for example ['~', '! ', '@' , '#'] cannot be sorted directly.
  2. The initial sequence must be the smallest sequence, otherwise all permutations cannot be listed. You can use quicksort to sort first and then use as input.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325304895&siteId=291194637