祝福:新春新年大吉大利。问鼎天下,谁与争锋。非递归非交换非转数组非无序全排列组合算法,诚邀比、测、评。

生成函数:组合的个数是位数的阶乘,规律是从头开始依次把后面各位的提到头位(不是交换位置),并依位次嵌套,把位次的从头开始依次把后面各位的提到头位。

泛型类型参数 五月五端午香囊(丁香,白术,肉桂,白芷,藿香,艾叶)

        static string 金箍棒(string 字符串, int 量, int 插位, int 调位)
        {
            if (插位 == 调位) return 字符串;
            插位 = Math.Abs(插位 %= 量); 调位 = Math.Abs(调位 %= 量);
            string 前 = "", 后 = "", 读 = "";
            int 头 = 0, 尾 = 量 - 1;
            Action<bool> 合成 = delegate(bool 选)
            {
                if (选) { 前 += 读; ++头; } else { 后 = 读 + 后; --尾; }
            };
            Action<bool> 读取 = delegate(bool 选)
            {
                读 = (选 ? 头 : 尾) != 调位 ? 字符串[(选 ? 头 : 尾)].ToString() : "";
                合成(选);
            };
            Action<bool> 处理 = delegate(bool 选)
            {
                if ((选 ? 头 : 尾) < 插位) 读取(选);
                else if ((选 ? 头 : 尾) == 插位)
                {
                    读 = 字符串[调位].ToString() + (插位 != 调位 ? 字符串[插位].ToString() : "");
                    合成(选);
                }
                else if ((选 ? 头 : 尾) > 插位) 读取(选);
            };
            do
            {/*字符量奇偶处理,采用折半我称双向处理,减少循环量提高处理速度,对整体减少时间是有效的2016-1-30 17:59*/
                if (头 <= 尾) 处理(true);
                if (头 < 尾) 处理(false);
            } while (头 <= 尾);
            return 前 + 后;
        }
        static void 金箍咒全排列组合(string 字符串)
        {
            string 金箍咒全排列组合 = "";
            int 量 = 字符串.Length, 嵌套量 = 量 - (量 > 2 ? 2 : 1)/*设置跳过位数*/, 跟 = 嵌套量;
            int[] 无限嵌套 = Enumerable.Repeat(0, 嵌套量).ToArray();
            do/*2016年1月29日16~17点钟完成:1.字符串不转数组2.字符串不进行位置交换只按变化的下标读取3.减少一半循环量直接获得2个排列组合效率高4.按顺序输出不需重新排序5.自动嵌套代码量比写固定嵌套少6.依然可以对数组执行。减少一个嵌套可节省很多循环量,用直接获取最后2位组合可节省一半循环量,这就是只循环生成一半的量,只是不是用反转数的逻辑,妙不可言!是这个算法的快诀窍,不过这种方式到底是否节省一半循环量觉得有点不可思议的感觉。*/
            {
                if (量 < 2) break;
                while (--跟 >= 0)/*嵌套逐级运算*/
                    if (无限嵌套[跟] >= 量 - 跟)
                    {
                        if (跟 - 1 < 0) break;/*防止越界*/
                        ++无限嵌套[跟 - 1];
                        无限嵌套[跟] = 0;
                    }
                if (无限嵌套[0] < 量)
                {
                    跟 = 0; /*Console.WriteLine(string.Join(" ", 无限嵌套));*/
                    foreach (int 嵌套 in 无限嵌套)
                        金箍咒全排列组合 = 金箍棒(跟 == 0 ? 字符串 : 金箍咒全排列组合, 量, 跟, 嵌套 + 跟++);
                    Console.Write(金箍咒全排列组合 + " " + (量 > 2 ? 金箍棒(金箍咒全排列组合, 量, 量 - 2, 量 - 1) + " " : ""));
                }
                ++无限嵌套[嵌套量 - 1];
                跟 = 嵌套量;
                金箍咒全排列组合 = "";
            } while (无限嵌套[0] < 量);
        }

主函数调用:

            Action 显示运算历时 = delegate()
            { Console.WriteLine("运行时间: {0}ms", 总运行时间.ElapsedMilliseconds); Console.WriteLine("准备就绪按回车键开始:"); Console.ReadKey(); 总运行时间 = Stopwatch.StartNew(); };
            金箍咒全排列组合("12"); 显示运算历时();
            金箍咒全排列组合("123"); 显示运算历时();
            金箍咒全排列组合("1234"); 显示运算历时();
            金箍咒全排列组合("12345"); 显示运算历时();
            金箍咒全排列组合("123456"); 显示运算历时();
            金箍咒全排列组合("1234567"); 显示运算历时();
            金箍咒全排列组合("12345678"); 显示运算历时();
            金箍咒全排列组合("123456789"); 显示运算历时();
            金箍咒全排列组合("0123456789"); 显示运算历时();


            金箍咒全排列组合("AB"); 显示运算历时();
            金箍咒全排列组合("ABC"); 显示运算历时();
            金箍咒全排列组合("ABCD"); 显示运算历时();
            金箍咒全排列组合("老少皆宜"); 显示运算历时();





猜你喜欢

转载自blog.csdn.net/xianfajushi/article/details/50643261
今日推荐