全排列递归与非递归python实现

       全排列就是,给定一个序列,列举出该序列中元素所有的排列情况,列举方法有递归和非递归两种,详细可以见这位大神写的博客:https://blog.csdn.net/jopus/article/details/18998403。我只列出来两个重要的图吧。

1.非递归:字典序法 ,如下图[1,2,3]的例子

2.递归方法

         递归方法就是将序列中第一位固定,然后将后面n-1为的全排列列举出来,取遍第一位所有取值,递归地得到所有排列。

 

python实现如下: 

# -*- coding:utf-8 -*-
# _author_ = xu_qn
# 全排列 分为两种:递归与非递归


# 递归方法
def recursion_permutation(list, first, last):
    if first >= last:  # 递归结束情况
        print(list)
    for i in range(first, last):  # first包含,last不包含
        list[i], list[first] = list[first], list[i]
        recursion_permutation(list, first+1, last)
        list[i], list[first] = list[first], list[i]  # 交换回来,还原成原来的序列放置重复交换


# 非递归:字典序法
def is_not_reverse(list):  # 判断是否为倒叙list
    for i in range(len(list)-1):
        if list[i] < list[i+1]:
            return True
    return False

def find_first_min(list):  # 从右到左是递增的 只需要找到最右大于pi的数
    for i in range(len(list)-1, 0, -1):
        if list[i] > list[0]:
            min_index = i
            break
    return min_index
def reverse_list(list,first,last):
    while first < last:
        if list[first] > list[last]:
            list[first], list[last] = list[last], list[first]
        first += 1
        last -= 1

def dictionary_permutation(list):
    while is_not_reverse(list):
        for i in range(len(list) - 2, -1, -1):
            if list[i] < list[i + 1]:  # 从左到右找到第一个左边小于右边的数pi 坐标i
                j = find_first_min(list[i:])  # 找到pi右边数字中比pi大的最小数下标
                list[i], list[j+i] = list[j+i], list[i]  # 交换pi,pj,pj在原list的坐标i+j
                reverse_list(list, i+1, len(list)-1)  # 将pi后的list倒转,变为升序
                print(list)




if __name__ == "__main__":
    list = [1, 2, 3, 4, 5]
    #recursion_permutation(list, 0, len(list))
    dictionary_permutation(list)

猜你喜欢

转载自blog.csdn.net/xuqn0606/article/details/81780724