首页 > 开发 > 综合 > 正文

递归枚举排列、组合的C#源码

2024-07-21 02:17:41
字体:
来源:转载
供稿:网友


大约是2001年时候用vs7 beta写的一点东西了,现在回看起来不是一般的幼稚。。。好处是还能运行:),看到csdn上有朋友要c# 的代码,我也不揣简陋,献丑了。(转换成vs03的工程了) 

combinatorics.cs代码清单

using system;
using system.collections;
using system.data;

     /// <summary>
     /// 组合数学函数集
     /// </summary>
     public class combinatorics
     {        
         #region 公共函数

         
         /// <summary>
         /// 把二维整形数组转换为数据表
         /// </summary>
         public static datatable twodemisionintarraytodatatable(int[, ]source)
         {
              datatable dt = new datatable();
              datarow dr;
              int i, j;
         
              int b1 = source.getupperbound(0), b2 = source.getupperbound(1);                //获取二维表的各维长度                         

              for (i = 0; i <= b1; i ++ )                                                         //以第二维长度创建数据表的各字段
                   dt.columns.add(i.tostring(), system.type.gettype("system.int32"));

              for (i = 0; i <= b2; i ++ )                                                         //对各返回排列循环
              {
                   dr = dt.newrow();                                                              //准备插入新行
                   for (j = 0; j <= b1; j ++ )                                                    //在新行中逐个填入返回排列的各元素次序                
                       dr[j.tostring()] = source[j, i];                                      //用序数指针获取原元素的值
                   dt.rows.add(dr);                                                               //插入新行
              }

              return dt;
         }    

         /// <summary>
         /// 连乘积函数         
         /// </summary>
         public static int product(int start, int finish)
         {
              int factorial = 1;
              for (int i = start; i <= finish; i ++ )
                   factorial *= i;
              return factorial;
         }                  

         /// <summary>
         /// 阶乘函数       
         /// </summary>
         public static int factorial(int n)
         {
              return product(2, n);
         }                           

         /// <summary>
         /// 排列数函数         
         /// </summary>
         public static int arrangecount(int m, int n)
         {
              return product(n - m + 1, n);        
         }
         
         /// <summary>
         /// 生成排列表函数     
         /// </summary>
         public static int[, ]arrange(int m, int n)
         {
              int a = arrangecount(m, n);               //求得排列数,安排返回数组的第一维
              int[, ]arrange = new int[m, a];           //定义返回数组
              arraylist e = new arraylist();            //设置元素表
              for (int i = 0; i < n; i ++ )
                   e.add(i + 1);
              arrange(ref arrange, e, m, 0, 0);
              return arrange;
         }

         /// <summary>
         /// 组合数函数         
         /// </summary>
         public static int combinationcount(int m, int n)
         {
              int a = product(n - m + 1, n), b = product(2, m);       //a=n-m+1 * ... * n ; b = m!
              return (int) a/b;                                            //c=a/b                              
         }

         /// <summary>
         /// 生成组合表函数     
         /// </summary>
         public static int[, ]combination(int m, int n)
         {
              int a = combinationcount(m, n);                //求得排列数,安排返回数组的第一维
              int[, ]combination = new int[m, a];            //定义返回数组
              arraylist e = new arraylist();                 //设置元素表
              for (int i = 0; i < n; i ++ )
                   e.add(i + 1);
              combination(ref combination, e, m, 0, 0);
              return combination;
         }
         

         #endregion
         
         #region 内部核心

         /// <summary>
         /// 排列函数
         /// </summary>
         /// <param name="reslut">返回值数组</param>
         /// <param name="elements">可供选择的元素数组</param>
         ///  <param name="m">目标选定元素个数</param>           
         /// <param name="x">当前返回值数组的列坐标</param>
         /// <param name="y">当前返回值数组的行坐标</param>
         private static void arrange(ref int[, ]reslut, arraylist elements, int m, int x, int y)
         {             
              int sub = arrangecount(m - 1, elements.count - 1);                    //求取当前子排列的个数
              for (int i = 0; i < elements.count; i++, y += sub)                    //每个元素均循环一次,每次循环后移动行指针
              {                  
                  int val = removeandwrite(elements, i, ref reslut, x, y, sub);                                                                                    
                   if (m > 1)                                                                 //递归条件为子排列数大于1
                       arrange(ref reslut, elements, m - 1, x + 1, y);
                   elements.insert(i, val);                                              //恢复刚才删除的元素                  
              }
         }
         
         /// <summary>
         /// 组合函数
         /// </summary>
         /// <param name="reslut">返回值数组</param>
         /// <param name="elements">可供选择的元素数组</param>
         ///  <param name="m">目标选定元素个数</param>           
         /// <param name="x">当前返回值数组的列坐标</param>
         /// <param name="y">当前返回值数组的行坐标</param>
         private static void combination(ref int[, ]reslut, arraylist elements, int m, int x, int y)
         {             
              arraylist tmpelements = new arraylist();                              //所有本循环使用的元素都将暂时存放在这个数组
              int elementscount = elements.count;                                        //先记录可选元素个数
              int sub;
              for (int i = elementscount - 1; i >= m - 1; i--, y += sub)            //从elementscount-1(即n-1)到m-1的循环,每次循环后移动行指针
              {
                   sub = combinationcount(m-1,i);                                   //求取当前子组合的个数
                   int val = removeandwrite(elements, 0, ref reslut, x, y, sub);                                                                 
                   tmpelements.add(val);                                                 //把这个可选元素存放到临时数组,循环结束后一并恢复到elements数组中                 
                   if (sub > 1 || (elements.count + 1 == m && elements.count > 0))  //递归条件为 子组合数大于1 或 可选元素个数+1等于当前目标选择元素个数且可选元素个数大于1
                       combination(ref reslut, elements, m - 1, x + 1, y);                                 
              }
              elements.insertrange(0, tmpelements);                                 //一次性把上述循环删除的可选元素恢复到可选元素数组中           
         }

         /// <summary>
         /// 返回由index指定的可选元素值,并在数组中删除之,再从y行开始在x列中连续写入subcomb个值
         /// </summary>
         private static int removeandwrite(arraylist elements, int index, ref int[, ]reslut, int x, int y, int count)
         {
              int val = (int) elements[index];
              elements.removeat(index);
              for (int i = 0; i < count; i ++ )
                   reslut[x, y + i] = val;              
              return val;
         }        
         
         #endregion 
     }




测试窗体frmtest.cs代码清单: 

using system;
using system.drawing;
using system.collections;
using system.componentmodel;
using system.windows.forms;
using system.data;

namespace combinatoricslib
{
     /// <summary>
     /// form1 的摘要说明。
     /// </summary>
     public class frmtest : system.windows.forms.form
     {
         private system.windows.forms.datagrid gridshow;
         private system.windows.forms.numericupdown numm;
         private system.windows.forms.button btngo;
         private system.windows.forms.domainupdown domainfunction;
         private system.windows.forms.statusbar statusbar1;
         private system.windows.forms.statusbarpanel panelerrmsg;
         private system.windows.forms.numericupdown numn;
         /// <summary>
         /// 必需的设计器变量。
         /// </summary>
         private system.componentmodel.container components = null;

         public frmtest()
         {
              //
              // windows 窗体设计器支持所必需的
              //
              initializecomponent();

              //
              // todo: 在 initializecomponent 调用后添加任何构造函数代码
              //
         }

         /// <summary>
         /// 清理所有正在使用的资源。
         /// </summary>
         protected override void dispose( bool disposing )
         {
              if( disposing )
              {
                   if (components != null) 
                   {
                       components.dispose();
                   }
              }
              base.dispose( disposing );
         }

         #region windows 窗体设计器生成的代码
         /// <summary>
         /// 设计器支持所需的方法 - 不要使用代码编辑器修改
         /// 此方法的内容。
         /// </summary>
         private void initializecomponent()
         {
              this.gridshow = new system.windows.forms.datagrid();
              this.domainfunction = new system.windows.forms.domainupdown();
              this.numm = new system.windows.forms.numericupdown();
              this.numn = new system.windows.forms.numericupdown();
              this.btngo = new system.windows.forms.button();
              this.statusbar1 = new system.windows.forms.statusbar();
              this.panelerrmsg = new system.windows.forms.statusbarpanel();
              ((system.componentmodel.isupportinitialize)(this.gridshow)).begininit();
              ((system.componentmodel.isupportinitialize)(this.numm)).begininit();
              ((system.componentmodel.isupportinitialize)(this.numn)).begininit();
              ((system.componentmodel.isupportinitialize)(this.panelerrmsg)).begininit();
              this.suspendlayout();
              // 
              // gridshow
              // 
              this.gridshow.alternatingbackcolor = system.drawing.color.lavender;
              this.gridshow.backcolor = system.drawing.color.whitesmoke;
              this.gridshow.backgroundcolor = system.drawing.color.lightgray;
              this.gridshow.borderstyle = system.windows.forms.borderstyle.none;
              this.gridshow.captionbackcolor = system.drawing.color.lightsteelblue;
              this.gridshow.captionforecolor = system.drawing.color.midnightblue;
              this.gridshow.datamember = "";
              this.gridshow.flatmode = true;
              this.gridshow.font = new system.drawing.font("tahoma", 8f);
              this.gridshow.forecolor = system.drawing.color.midnightblue;
              this.gridshow.gridlinecolor = system.drawing.color.gainsboro;
              this.gridshow.gridlinestyle = system.windows.forms.datagridlinestyle.none;
              this.gridshow.headerbackcolor = system.drawing.color.midnightblue;
              this.gridshow.headerfont = new system.drawing.font("tahoma", 8f, system.drawing.fontstyle.bold);
              this.gridshow.headerforecolor = system.drawing.color.whitesmoke;
              this.gridshow.linkcolor = system.drawing.color.teal;
              this.gridshow.location = new system.drawing.point(24, 88);
              this.gridshow.name = "gridshow";
              this.gridshow.parentrowsbackcolor = system.drawing.color.gainsboro;
              this.gridshow.parentrowsforecolor = system.drawing.color.midnightblue;
              this.gridshow.readonly = true;
              this.gridshow.selectionbackcolor = system.drawing.color.cadetblue;
              this.gridshow.selectionforecolor = system.drawing.color.whitesmoke;
              this.gridshow.size = new system.drawing.size(648, 344);
              this.gridshow.tabindex = 0;
              // 
              // domainfunction
              // 
              this.domainfunction.backcolor = system.drawing.systemcolors.info;
              this.domainfunction.font = new system.drawing.font("宋体", 36f, system.drawing.fontstyle.regular, system.drawing.graphicsunit.point, ((system.byte)(134)));
              this.domainfunction.forecolor = system.drawing.color.teal;
              this.domainfunction.items.add("c");
              this.domainfunction.items.add("a");
              this.domainfunction.location = new system.drawing.point(24, 8);
              this.domainfunction.name = "domainfunction";
              this.domainfunction.readonly = true;
              this.domainfunction.size = new system.drawing.size(48, 62);
              this.domainfunction.tabindex = 1;
              this.domainfunction.text = "c";
              // 
              // numm
              // 
              this.numm.backcolor = system.drawing.color.peachpuff;
              this.numm.font = new system.drawing.font("宋体", 12f, system.drawing.fontstyle.regular, system.drawing.graphicsunit.point, ((system.byte)(134)));
              this.numm.forecolor = system.drawing.color.teal;
              this.numm.location = new system.drawing.point(80, 8);
              this.numm.maximum = new system.decimal(new int[] {
                                                                            20,
                                                                            0,
                                                                            0,
                                                                            0});
              this.numm.minimum = new system.decimal(new int[] {
                                                                            1,
                                                                            0,
                                                                            0,
                                                                            0});
              this.numm.name = "numm";
              this.numm.size = new system.drawing.size(56, 26);
              this.numm.tabindex = 4;
              this.numm.value = new system.decimal(new int[] {
                                                                         2,
                                                                         0,
                                                                         0,
                                                                         0});
              // 
              // numn
              // 
              this.numn.backcolor = system.drawing.color.bisque;
              this.numn.font = new system.drawing.font("宋体", 12f);
              this.numn.forecolor = system.drawing.color.teal;
              this.numn.location = new system.drawing.point(80, 40);
              this.numn.maximum = new system.decimal(new int[] {
                                                                            25,
                                                                            0,
                                                                            0,
                                                                            0});
              this.numn.minimum = new system.decimal(new int[] {
                                                                            1,
                                                                            0,
                                                                            0,
                                                                            0});
              this.numn.name = "numn";
              this.numn.size = new system.drawing.size(56, 26);
              this.numn.tabindex = 5;
              this.numn.value = new system.decimal(new int[] {
                                                                         4,
                                                                         0,
                                                                         0,
                                                                         0});
              // 
              // btngo
              // 
              this.btngo.backcolor = system.drawing.color.paleturquoise;
              this.btngo.location = new system.drawing.point(184, 24);
              this.btngo.name = "btngo";
              this.btngo.size = new system.drawing.size(88, 32);
              this.btngo.tabindex = 6;
              this.btngo.text = "go!";
              this.btngo.click += new system.eventhandler(this.btngo_click);
              // 
              // statusbar1
              // 
              this.statusbar1.location = new system.drawing.point(0, 453);
              this.statusbar1.name = "statusbar1";
              this.statusbar1.panels.addrange(new system.windows.forms.statusbarpanel[] {
                                                                                                         this.panelerrmsg});
              this.statusbar1.showpanels = true;
              this.statusbar1.size = new system.drawing.size(704, 32);
              this.statusbar1.tabindex = 7;
              this.statusbar1.text = "statusbar1";
              // 
              // panelerrmsg
              // 
              this.panelerrmsg.autosize = system.windows.forms.statusbarpanelautosize.contents;
              this.panelerrmsg.text = "idle";
              this.panelerrmsg.width = 39;
              // 
              // frmtest
              // 
              this.autoscalebasesize = new system.drawing.size(6, 14);
              this.clientsize = new system.drawing.size(704, 485);
              this.controls.add(this.statusbar1);
              this.controls.add(this.btngo);
              this.controls.add(this.numn);
              this.controls.add(this.numm);
              this.controls.add(this.domainfunction);
              this.controls.add(this.gridshow);
              this.maximizebox = false;
              this.name = "frmtest";
              this.startposition = system.windows.forms.formstartposition.centerscreen;
              this.text = "frmtest";
              ((system.componentmodel.isupportinitialize)(this.gridshow)).endinit();
              ((system.componentmodel.isupportinitialize)(this.numm)).endinit();
              ((system.componentmodel.isupportinitialize)(this.numn)).endinit();
              ((system.componentmodel.isupportinitialize)(this.panelerrmsg)).endinit();
              this.resumelayout(false);

         }
         #endregion

         /// <summary>
         /// 应用程序的主入口点。
         /// </summary>
         [stathread]
         static void main() 
         {
              application.run(new frmtest());
         }

         private void btngo_click(object sender, system.eventargs e)
         {
              int[, ]reslut;
              int m = (int)numm.value, n = (int)numn.value;
              
              if (m <= n)
              {
                   panelerrmsg.text = "running...";
                   if (domainfunction.text == "a")                
                       reslut = combinatorics.arrange(m, n);
                   else
                       reslut = combinatorics.combination(m, n);                        
                   panelerrmsg.text = "showing...";
                   gridshow.datasource = combinatorics.twodemisionintarraytodatatable(reslut);
                   panelerrmsg.text = "idle";
              }
              else          
                   panelerrmsg.text = "input number is invalid";
         }
     }
}

运行效果如图:
 

感觉没什么好废话的,用datatable输出就是为了方便绑定实体值(比如做攻击字典)的枚举。各路高人见笑了。 
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表