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

 

         using System;    

  1. using System.Collections;    
  2. using System.Data;    
  3.      /// <summary>    
  4.      /// 组合数学函数集    
  5.      /// </summary>    
  6. public class Combinatorics   
  7. {  
  8.     #region 公共函数   
  9.     /// <summary>    
  10.     /// 把二维整形数组转换为数据表    
  11.     /// </summary>    
  12.     public static DataTable TwoDemisionIntArrayToDataTable(int[,] source)   
  13.     {   
  14.         DataTable dt = new DataTable();   
  15.         DataRow dr;   
  16.         int i, j;   
  17.         int b1 = source.GetUpperBound(0), b2 = source.GetUpperBound(1);                //获取二维表的各维长度                             
  18.         for (i = 0; i <= b1; i++)                                                         //以第二维长度创建数据表的各字段    
  19.             dt.Columns.Add(i.ToString(), System.Type.GetType("System.Int32"));   
  20.         for (i = 0; i <= b2; i++)                                                         //对各返回排列循环    
  21.         {   
  22.             dr = dt.NewRow();                                                              //准备插入新行    
  23.             for (j = 0; j <= b1; j++)                                                    //在新行中逐个填入返回排列的各元素次序                    
  24.                 dr[j.ToString()] = source[j, i];                                      //用序数指针获取原元素的值    
  25.             dt.Rows.Add(dr);                                                               //插入新行    
  26.         }   
  27.         return dt;   
  28.     }   
  29.     /// <summary>    
  30.     /// 连乘积函数             
  31.     /// </summary>    
  32.     public static int Product(int start, int finish)   
  33.     {   
  34.         int factorial = 1;   
  35.         for (int i = start; i <= finish; i++)   
  36.             factorial *= i;   
  37.         return factorial;   
  38.     }   
  39.     /// <summary>    
  40.     /// 阶乘函数           
  41.     /// </summary>    
  42.     public static int Factorial(int n)   
  43.     {   
  44.         return Product(2, n);   
  45.     }   
  46.     /// <summary>    
  47.     /// 排列数函数             
  48.     /// </summary>    
  49.     public static int ArrangeCount(int m, int n)   
  50.     {   
  51.         return Product(n - m + 1, n);   
  52.     }   
  53.     /// <summary>    
  54.     /// 生成排列表函数         
  55.     /// </summary>    
  56.     public static int[,] Arrange(int m, int n)   
  57.     {   
  58.         int A = ArrangeCount(m, n);               //求得排列数,安排返回数组的第一维    
  59.         int[,] arrange = new int[m, A];           //定义返回数组    
  60.         ArrayList e = new ArrayList();            //设置元素表    
  61.         for (int i = 0; i < n; i++)   
  62.             e.Add(i + 1);   
  63.         Arrange(ref arrange, e, m, 0, 0);   
  64.         return arrange;   
  65.     }   
  66.     /// <summary>    
  67.     /// 组合数函数             
  68.     /// </summary>    
  69.     public static int CombinationCount(int m, int n)   
  70.     {   
  71.         int a = Product(n - m + 1, n), b = Product(2, m);       //a=n-m+1 * ... * n ; b = m!    
  72.         return (int)a / b;                                            //c=a/b                                  
  73.     }   
  74.     /// <summary>    
  75.     /// 生成组合表函数         
  76.     /// </summary>    
  77.     public static int[,] Combination(int m, int n)   
  78.     {   
  79.         int A = CombinationCount(m, n);                //求得排列数,安排返回数组的第一维   
  80.         int[,] combination = new int[m, A];            //定义返回数组    
  81.         ArrayList e = new ArrayList();                 //设置元素表    
  82.         for (int i = 0; i < n; i++)   
  83.             e.Add(i + 1);   
  84.         Combination(ref combination, e, m, 0, 0);   
  85.         return combination;   
  86.     }  
  87.     #endregion  
  88.     #region 内部核心   
  89.     /// <summary>    
  90.     /// 排列函数    
  91.     /// </summary>    
  92.     /// <param name="reslut">返回值数组</param>    
  93.     /// <param name="elements">可供选择的元素数组</param>    
  94.     ///  <param name="m">目标选定元素个数</param>               
  95.     /// <param name="x">当前返回值数组的列坐标</param>    
  96.     /// <param name="y">当前返回值数组的行坐标</param>    
  97.     private static void Arrange(ref int[,] reslut, ArrayList elements, int m, int x, int y)   
  98.     {   
  99.         int sub = ArrangeCount(m - 1, elements.Count - 1);                    //求取当前子排列的个数    
  100.         for (int i = 0; i < elements.Count; i++, y += sub)                    //每个元素均循环一次,每次循环后移动行指针    
  101.         {   
  102.             int val = RemoveAndWrite(elements, i, ref reslut, x, y, sub);   
  103.             if (m > 1)                                                                 //递归条件为子排列数大于1    
  104.                 Arrange(ref reslut, elements, m - 1, x + 1, y);   
  105.             elements.Insert(i, val);                                              //恢复刚才删除的元素                      
  106.         }   
  107.     }   
  108.     /// <summary>    
  109.     /// 组合函数    
  110.     /// </summary>    
  111.     /// /// <param name="reslut">返回值数组</param>    
  112.     /// <param name="elements">可供选择的元素数组</param>    
  113.     ///  <param name="m">目标选定元素个数</param>               
  114.     /// <param name="x">当前返回值数组的列坐标</param>    
  115.     /// <param name="y">当前返回值数组的行坐标</param>    
  116.     private static void Combination(ref int[,] reslut, ArrayList elements, int m, int x, int y)   
  117.     {   
  118.         ArrayList tmpElements = new ArrayList();                              //所有本循环使用的元素都将暂时存放在这个数组    
  119.         int elementsCount = elements.Count;                                        //先记录可选元素个数    
  120.         int sub;   
  121.         for (int i = elementsCount - 1; i >= m - 1; i--, y += sub)            //从elementsCount-1(即n-1)到m-1的循环,每次循环后移动行指针    
  122.         {   
  123.             sub = CombinationCount(m - 1, i);                                   //求取当前子组合的个数    
  124.             int val = RemoveAndWrite(elements, 0, ref reslut, x, y, sub);   
  125.             tmpElements.Add(val);                                                 //把这个可选元素存放到临时数组,循环结束后一并恢复到elements数组中                     
  126.             if (sub > 1 || (elements.Count + 1 == m && elements.Count > 0))  //递归条件为 子组合数大于1 或 可选元素个数+1等于当前目标选择元素个数且可选元素个数大于1    
  127.                 Combination(ref reslut, elements, m - 1, x + 1, y);   
  128.         }   
  129.         elements.InsertRange(0, tmpElements);                                 //一次性把上述循环删除的可选元素恢复到可选元素数组中               
  130.     }   
  131.     /// <summary>    
  132.     /// 返回由Index指定的可选元素值,并在数组中删除之,再从y行开始在x列中连续写入subComb个值    
  133.     /// </summary>    
  134.     private static int RemoveAndWrite(ArrayList elements, int index, ref int[,] reslut, int x, int y, int count)   
  135.     {   
  136.         int val = (int)elements[index];   
  137.         elements.RemoveAt(index);   
  138.         for (int i = 0; i < count; i++)   
  139.             reslut[x, y + i] = val;   
  140.         return val;   
  141.     }  
  142.     #endregion   
  143. }  

测试代码:

  1. using System;    
  2. using System.Drawing;    
  3. using System.Collections;    
  4. using System.ComponentModel;    
  5. using System.Windows.Forms;    
  6. using System.Data;   
  7. namespace CombinatoricsLib   
  8. {   
  9.     /// <summary>    
  10.     /// Form1 的摘要说明。    
  11.     /// </summary>    
  12.     public class frmTest : System.Windows.Forms.Form   
  13.     {   
  14.         private System.Windows.Forms.DataGrid gridShow;   
  15.         private System.Windows.Forms.NumericUpDown numM;   
  16.         private System.Windows.Forms.Button btnGo;   
  17.         private System.Windows.Forms.DomainUpDown domainFunction;   
  18.         private System.Windows.Forms.StatusBar statusBar1;   
  19.         private System.Windows.Forms.StatusBarPanel panelErrMsg;   
  20.         private System.Windows.Forms.NumericUpDown numN;   
  21.         /// <summary>    
  22.         /// 必需的设计器变量。    
  23.         /// </summary>    
  24.         private System.ComponentModel.Container components = null;   
  25.         public frmTest()   
  26.         {   
  27.             //    
  28.             // Windows 窗体设计器支持所必需的    
  29.             //    
  30.             InitializeComponent();   
  31.             //    
  32.             // TODO: 在 InitializeComponent 调用后添加任何构造函数代码    
  33.             //    
  34.         }   
  35.         /// <summary>    
  36.         /// 清理所有正在使用的资源。    
  37.         /// </summary>    
  38.         protected override void Dispose(bool disposing)   
  39.         {   
  40.             if (disposing)   
  41.             {   
  42.                 if (components != null)   
  43.                 {   
  44.                     components.Dispose();   
  45.                 }   
  46.             }   
  47.             base.Dispose(disposing);   
  48.         }  
  49.         #region Windows 窗体设计器生成的代码   
  50.         /// <summary>    
  51.         /// 设计器支持所需的方法 - 不要使用代码编辑器修改    
  52.         /// 此方法的内容。    
  53.         /// </summary>    
  54.         private void InitializeComponent()   
  55.         {   
  56.             this.gridShow = new System.Windows.Forms.DataGrid();   
  57.             this.domainFunction = new System.Windows.Forms.DomainUpDown();   
  58.             this.numM = new System.Windows.Forms.NumericUpDown();   
  59.             this.numN = new System.Windows.Forms.NumericUpDown();   
  60.             this.btnGo = new System.Windows.Forms.Button();   
  61.             this.statusBar1 = new System.Windows.Forms.StatusBar();   
  62.             this.panelErrMsg = new System.Windows.Forms.StatusBarPanel();   
  63.             ((System.ComponentModel.ISupportInitialize)(this.gridShow)).BeginInit();   
  64.             ((System.ComponentModel.ISupportInitialize)(this.numM)).BeginInit();   
  65.             ((System.ComponentModel.ISupportInitialize)(this.numN)).BeginInit();   
  66.             ((System.ComponentModel.ISupportInitialize)(this.panelErrMsg)).BeginInit();   
  67.             this.SuspendLayout();   
  68.             //     
  69.             // gridShow    
  70.             //     
  71.             this.gridShow.AlternatingBackColor = System.Drawing.Color.Lavender;   
  72.             this.gridShow.BackColor = System.Drawing.Color.WhiteSmoke;   
  73.             this.gridShow.BackgroundColor = System.Drawing.Color.LightGray;   
  74.             this.gridShow.BorderStyle = System.Windows.Forms.BorderStyle.None;   
  75.             this.gridShow.CaptionBackColor = System.Drawing.Color.LightSteelBlue;   
  76.             this.gridShow.CaptionForeColor = System.Drawing.Color.MidnightBlue;   
  77.             this.gridShow.DataMember = "";   
  78.             this.gridShow.FlatMode = true;   
  79.             this.gridShow.Font = new System.Drawing.Font("Tahoma", 8F);   
  80.             this.gridShow.ForeColor = System.Drawing.Color.MidnightBlue;   
  81.             this.gridShow.GridLineColor = System.Drawing.Color.Gainsboro;   
  82.             this.gridShow.GridLineStyle = System.Windows.Forms.DataGridLineStyle.None;   
  83.             this.gridShow.HeaderBackColor = System.Drawing.Color.MidnightBlue;   
  84.             this.gridShow.HeaderFont = new System.Drawing.Font("Tahoma", 8F, System.Drawing.FontStyle.Bold);   
  85.             this.gridShow.HeaderForeColor = System.Drawing.Color.WhiteSmoke;   
  86.             this.gridShow.LinkColor = System.Drawing.Color.Teal;   
  87.             this.gridShow.Location = new System.Drawing.Point(24, 88);   
  88.             this.gridShow.Name = "gridShow";   
  89.             this.gridShow.ParentRowsBackColor = System.Drawing.Color.Gainsboro;   
  90.             this.gridShow.ParentRowsForeColor = System.Drawing.Color.MidnightBlue;   
  91.             this.gridShow.ReadOnly = true;   
  92.             this.gridShow.SelectionBackColor = System.Drawing.Color.CadetBlue;   
  93.             this.gridShow.SelectionForeColor = System.Drawing.Color.WhiteSmoke;   
  94.             this.gridShow.Size = new System.Drawing.Size(648, 344);   
  95.             this.gridShow.TabIndex = 0;   
  96.             //     
  97.             // domainFunction    
  98.             //     
  99.             this.domainFunction.BackColor = System.Drawing.SystemColors.Info;   
  100.             this.domainFunction.Font = new System.Drawing.Font("宋体", 36F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(134)));   
  101.             this.domainFunction.ForeColor = System.Drawing.Color.Teal;   
  102.             this.domainFunction.Items.Add("C");   
  103.             this.domainFunction.Items.Add("A");   
  104.             this.domainFunction.Location = new System.Drawing.Point(24, 8);   
  105.             this.domainFunction.Name = "domainFunction";   
  106.             this.domainFunction.ReadOnly = true;   
  107.             this.domainFunction.Size = new System.Drawing.Size(48, 62);   
  108.             this.domainFunction.TabIndex = 1;   
  109.             this.domainFunction.Text = "C";   
  110.             //     
  111.             // numM    
  112.             //     
  113.             this.numM.BackColor = System.Drawing.Color.PeachPuff;   
  114.             this.numM.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(134)));   
  115.             this.numM.ForeColor = System.Drawing.Color.Teal;   
  116.             this.numM.Location = new System.Drawing.Point(80, 8);   
  117.             this.numM.Maximum = new System.Decimal(new int[] {    
  118.                                                                             20,    
  119.                                                                             0,    
  120.                                                                             0,    
  121.                                                                             0});   
  122.             this.numM.Minimum = new System.Decimal(new int[] {    
  123.                                                                             1,    
  124.                                                                             0,    
  125.                                                                             0,    
  126.                                                                             this.numM.Name = "numM"});   
  127.             this.numM.Size = new System.Drawing.Size(56, 26);   
  128.             this.numM.TabIndex = 4;   
  129.             this.numM.Value = new System.Decimal(new int[] {    
  130.                                                                          2,    
  131.                                                                          0,    
  132.                                                                          0,    
  133.                                                                          0});   
  134.             //     
  135.             // numN    
  136.             //     
  137.             this.numN.BackColor = System.Drawing.Color.Bisque;   
  138.             this.numN.Font = new System.Drawing.Font("宋体", 12F);   
  139.             this.numN.ForeColor = System.Drawing.Color.Teal;   
  140.             this.numN.Location = new System.Drawing.Point(80, 40);   
  141.             this.numN.Maximum = new System.Decimal(new int[] {    
  142.                                                                             25,    
  143.                                                                             0,    
  144.                                                                             0,    
  145.                                                                             0});   
  146.             this.numN.Minimum = new System.Decimal(new int[] {    
  147.                                                                             1,    
  148.                                                                             this.numN.Name = "numN"});   
  149.             this.numN.Size = new System.Drawing.Size(56, 26);   
  150.             this.numN.TabIndex = 5;   
  151.             this.numN.Value = new System.Decimal(new int[] {    
  152.                                                                          4,    
  153.                                                                          0,    
  154.                                                                          0,    
  155.                                                                          0});   
  156.             //     
  157.             // btnGo    
  158.             //     
  159.             this.btnGo.BackColor = System.Drawing.Color.PaleTurquoise;   
  160.             this.btnGo.Location = new System.Drawing.Point(184, 24);   
  161.             this.btnGo.Name = "btnGo";   
  162.             this.btnGo.Size = new System.Drawing.Size(88, 32);   
  163.             this.btnGo.TabIndex = 6;   
  164.             this.btnGo.Text = "Go!";   
  165.             this.btnGo.Click += new System.EventHandler(this.btnGo_Click);   
  166.             //     
  167.             // statusBar1    
  168.             //     
  169.             this.statusBar1.Location = new System.Drawing.Point(0, 453);   
  170.             this.statusBar1.Name = "statusBar1";   
  171.             this.statusBar1.Panels.AddRange(new System.Windows.Forms.StatusBarPanel[] {    
  172.                                                                                         this.statusBar1.Size = new System.Drawing.Size(704, 32)});   
  173.             this.statusBar1.TabIndex = 7;   
  174.             this.statusBar1.Text = "statusBar1";   
  175.             //     
  176.             // panelErrMsg    
  177.             //     
  178.             this.panelErrMsg.AutoSize = System.Windows.Forms.StatusBarPanelAutoSize.Contents;   
  179.             this.panelErrMsg.Text = "Idle";   
  180.             this.panelErrMsg.Width = 39;   
  181.             //     
  182.             // frmTest    
  183.             //     
  184.             this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);   
  185.             this.ClientSize = new System.Drawing.Size(704, 485);   
  186.             this.Controls.Add(this.statusBar1);   
  187.             this.Controls.Add(this.btnGo);   
  188.             this.Controls.Add(this.numN);   
  189.             this.Controls.Add(this.numM);   
  190.             this.Controls.Add(this.domainFunction);   
  191.             this.Controls.Add(this.gridShow);   
  192.             this.MaximizeBox = false;   
  193.             this.Name = "frmTest";   
  194.             this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;   
  195.             this.Text = "frmTest";   
  196.             ((System.ComponentModel.ISupportInitialize)(this.gridShow)).EndInit();   
  197.             ((System.ComponentModel.ISupportInitialize)(this.numM)).EndInit();   
  198.             ((System.ComponentModel.ISupportInitialize)(this.numN)).EndInit();   
  199.             ((System.ComponentModel.ISupportInitialize)(this.panelErrMsg)).EndInit();   
  200.             this.ResumeLayout(false);   
  201.         }  
  202.         #endregion   
  203.         /// <summary>    
  204.         /// 应用程序的主入口点。    
  205.         /// </summary>    
  206.         [STAThread]   
  207.         static void Main()   
  208.         {   
  209.             Application.Run(new frmTest());   
  210.         }   
  211.         private void btnGo_Click(object sender, System.EventArgs e)   
  212.         {   
  213.             int[,] reslut;   
  214.             int m = (int)numM.Value, n = (int)numN.Value;   
  215.             if (m <= n)   
  216.             {   
  217.                 panelErrMsg.Text = "Running...";   
  218.                 if (domainFunction.Text == "A")   
  219.                     reslut = Combinatorics.Arrange(m, n);   
  220.                 reslut = Combinatorics.Combination(m, n);   
  221.                 panelErrMsg.Text = "Showing...";   
  222.                 gridShow.DataSource = Combinatorics.TwoDemisionIntArrayToDataTable(reslut);   
  223.                 panelErrMsg.Text = "Idle";   
  224.             }   
  225.             else  
  226.                 panelErrMsg.Text = "Input number is invalid";   
  227.         }   
  228.     }   
  229. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值