博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
字典序全排列算法研究
阅读量:7065 次
发布时间:2019-06-28

本文共 5533 字,大约阅读时间需要 18 分钟。

  最近对数学方面很有兴趣,周末和同学去大学蹭课,其中在讲排列组合的时候讲到了全排列的字典序生成算法,我觉得这个想法真的挺好,去网上找了找,貌似都是递归求全排列,没有讲到这个算法的,今天我将这个算法写出来了,发在这里,以后学习。

  非递归方法(字典序法):

  这种算法被用在了C++的STL库中。

  对给定的字符集中的字符规定了一个先后关系,在此基础上规定两个全排列的先后是从左到右逐个比较对应的字符的先后。

 [例]字符集{
1,2,3},较小的数字较先,这样按字典序生成的全排列是:     123,132,213,231,312,321

  ※ 一个全排列可看做一个字符串,字符串可有前缀后缀

  生成给定全排列的下一个排列.所谓一个的下一个就是这一个与下一个之间没有其他的。这就要求这一个与下一个有尽可能共同前,也即变化限制在尽可能后缀上。

[例]839647521是1--9的排列。1—9的排列最前面的是123456789,最后面的987654321,从右向左扫描若都是增的,就到了987654321,也就没有下一个了。否则找出第一次出现下降的位置。
【例】 一般而言,设P是[1,n]的一个全排列。      P=P1P2…Pn=P1P2…Pj-1PjPj+1…Pk-1PkPk+1…Pn    find:  j=max{i|Pi
Pj}      1, 对换Pj,Pk,       2, 将Pj+1…Pk-1PjPk+1…Pn翻转 P’= P1P2…Pj-1PkPn…Pk+1PjPk-1…Pj+1即P的下一个
【例】 如何得到346987521的下一个    1,从尾部往前找第一个P(i-1) < P(i)的位置            3 4 6 <- 9 <- 8 <- 7 <- 5 <- 2 <- 1        最终找到6是第一个变小的数字,记录下6的位置i-1    2,从i位置往后找到最后一个大于6的数            3 4 6 -> 9 -> 8 -> 7 5 2 1        最终找到7的位置,记录位置为m    3,交换位置i-1和m的值            3 4 7 9 8 6 5 2 1    4,倒序i位置后的所有数据            3 4 7 1 2 5 6 8 9    则347125689为346987521的下一个排列

  依照上面的讲述不难将代码写出来,如下:

private static void PermutationList()        {            int fromIndex, endIndex, changeIndex;            Sort(0, length - 1);            do            {                // 输出一种全排列                Output();                fromIndex = endIndex = length - 1;                // 向前查找第一个变小的元素                while (fromIndex > 0 && words[fromIndex] < words[fromIndex - 1]) --fromIndex;                changeIndex = fromIndex;                if (fromIndex == 0) break;                // 向后查找最后一个大于words[fromIndex-1]的元素                while (changeIndex + 1 < length && words[changeIndex + 1] > words[fromIndex - 1]) ++changeIndex;                Swap(fromIndex - 1, changeIndex);   // 交换两个值                InvertArray(fromIndex, endIndex);   // 对后面的所有值进行反向处理            } while (true);        }

  递归方法求全排列:

  递归方法很容易理解:分别将每个位置交换到最前面位,之后全排列剩下的位。

【例】递归全排列 1 2 3 4 5    1,for循环将每个位置的数据交换到第一位            swap(1,1~5)    2,按相同的方式全排列剩余的位

  由于递归方法很容易理解,而且网上也有很多的资料,所以不过多讲述,代码如下:

///         /// 递归方式生成全排列的方法        ///         /// 全排列的起始位置        /// 全排列的终止位置        private static void PermutationList(int fromIndex, int endIndex)        {            if (fromIndex == endIndex)                Output();            else            {                for (int index = fromIndex; index <= endIndex; ++index)                {                    // 此处排序主要是为了生成字典序全排列,否则递归会打乱字典序                    Sort(fromIndex, endIndex);                    Swap(fromIndex, index);                    PermutationList(fromIndex + 1, endIndex);                    Swap(fromIndex, index);                }            }        }

以上代码只截取了部分关键代码,所有代码如下:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace Algorithms{    class Permutation    {        private static int MAXLENGTH = 20;        private static int length;        private static char[] words = new char[MAXLENGTH];        private static void Swap(int indexX, int indexY)        {            if (indexX != indexY)            {                char ch = words[indexX];                words[indexX] = words[indexY];                words[indexY] = ch;            }        }        private static void InvertArray(int fromIndex, int endIndex)        {            for (; fromIndex < endIndex; ++fromIndex, --endIndex)                Swap(fromIndex, endIndex);        }        private static void Sort(int fromIndex, int endIndex)        {            Array.Sort(words, fromIndex, endIndex - fromIndex + 1);        }        private static void Output()        {            for (int index = 0; index < length; ++index)                Console.Write(words[index] + " ");            Console.WriteLine();        }        private static void PermutationList()        {            int fromIndex, endIndex, changeIndex;            Sort(0, length - 1);            do            {                // 输出一种全排列                Output();                fromIndex = endIndex = length - 1;                // 向前查找第一个变小的元素                while (fromIndex > 0 && words[fromIndex] < words[fromIndex - 1]) --fromIndex;                changeIndex = fromIndex;                if (fromIndex == 0) break;                // 向后查找最后一个大于words[fromIndex-1]的元素                while (changeIndex + 1 < length && words[changeIndex + 1] > words[fromIndex - 1]) ++changeIndex;                Swap(fromIndex - 1, changeIndex);   // 交换两个值                InvertArray(fromIndex, endIndex);   // 对后面的所有值进行反向处理            } while (true);        }        ///         /// 递归方式生成全排列的方法        ///         /// 全排列的起始位置        /// 全排列的终止位置        private static void PermutationList(int fromIndex, int endIndex)        {            if (fromIndex == endIndex)                Output();            else            {                for (int index = fromIndex; index <= endIndex; ++index)                {                    // 此处排序主要是为了生成字典序全排列,否则递归会打乱字典序                    Sort(fromIndex, endIndex);                    Swap(fromIndex, index);                    PermutationList(fromIndex + 1, endIndex);                    Swap(fromIndex, index);                }            }        }        public static void PermutationTest()        {            Console.Write("please input the permutation words:");            words = Console.ReadLine().ToCharArray();            length = words.Count();            PermutationList();            Console.ReadLine();        }    }}
View Code

 

运行结果:

转载于:https://www.cnblogs.com/pmars/p/3458289.html

你可能感兴趣的文章
MUI下拉刷新
查看>>
C#操纵Excel,此工作薄包含嵌入对象,Office 2007的设定方法
查看>>
【转载】ANSYS 动力分析 (9) - 瞬态动力分析 (1)
查看>>
PHP观察者模式的简单实现
查看>>
Trivial File Transfer Protocol (TFTP)
查看>>
C++版 - LeetCode 144. Binary Tree Preorder Traversal (二叉树先根序遍历,非递归)
查看>>
前端开发之旅-zopim在线即时聊天客服
查看>>
c++模板实现抽象工厂
查看>>
节日营销!这样搞-App运营日常
查看>>
谁是“少数幸福的人”?
查看>>
坦克大战--Java类型 ---- (2)按键设置和用户名的输入
查看>>
手机操作系统:自主力量能否崛起
查看>>
Shell在大数据时代的魅力:从一道百度大数据面试题想到的点滴
查看>>
说说參数传递(泛型托付)
查看>>
CentOS6.10下安装mysql-5.7.24
查看>>
【C#公共帮助类】 ToolsHelper帮助类
查看>>
八皇后问题
查看>>
切蛋糕
查看>>
关于对于CSS的字体单位
查看>>
TCP协议学习总结(上)
查看>>