活到老学到老

现学现卖

博客园 首页 新随笔 联系 订阅 管理
PermutationGen用来枚举{1,...,n}的所有全排列。
D类用来计算行列式,只能对数值进行计算。
代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Determinant
{
    
class Program
    {
        
static void Main(string[] args)
        {
            
//Console.WriteLine(D.SwitchCount(new int[] { 3, 2, 5, 1, 4 }));

            
//D.PermutationGen pg = new D.PermutationGen(4);
            
//pg.FastIteration = true;
            
//foreach (var p in pg)
            
//{
            
//    Console.WriteLine(pg.PermutationToString(p));
            
//}

            D d1 
= new D(3);
            d1.Data[
00= 1;
            d1.Data[
01= 2;
            d1.Data[
02= -4;
            d1.Data[
10= -2;
            d1.Data[
11= 2;
            d1.Data[
12= 1;
            d1.Data[
20= -3;
            d1.Data[
21= 4;
            d1.Data[
22= -2;
            Console.WriteLine(d1.Value);

            D d2 
= new D(2);
            d2.Data[
00= 3;
            d2.Data[
01= 12;
            d2.Data[
10= 2;
            d2.Data[
11= 1;
            Console.WriteLine(d2.Value);
            Console.ReadKey();
        }
    }

    
public class D
    {
        
/// <summary>
        
/// 计算1-n的一个全排列的逆序数
        
/// </summary>
        
/// <param name="permutation">a permutation of 1-permutation.Length</param>
        
/// <returns></returns>
        public static int SwitchCount(int[] permutation)
        {
            
int count = 0;
            
if (permutation == null || permutation.Length == 0throw new ArgumentException("输入不能为空""permutation");
            
if (permutation.Length == 1)
            {
                
return 0;
            }
            
for (int i = 0; i < permutation.Length; i++)
            {
                
if (permutation[i] < 1 || permutation[i] > permutation.Length) throw new ArgumentException("只计算1-n的排列的逆序数");
            }
            
for (int i = 0; i < permutation.Length; i++)
            {
                
for (int j = i + 1; j < permutation.Length; j++)
                {
                    
if (permutation[i] > permutation[j]) count++;
                    
else if (permutation[i] == permutation[j]) throw new ArgumentException(String.Format("数字{0}重复出现在位置{1}和{2}", permutation[i], i, j), "permutation");
                }
            }
            
return count;
        }

        
double[,] data;
        
int n;
        PermutationGen pg;

        
public D(int rank)
        {
            
if (rank < 2throw new ArgumentException("Rank is at least 2.");
            n 
= rank;
            data 
= new double[rank, rank];
            data.Initialize();
        }

        
public double[,] Data
        {
            
get
            {
                
return data;
            }
        }

        
public double Value //calculate the value form the data given
        {
            
get
            {
                
double v = 0;
                
if (pg == null)
                {
                    pg 
= new PermutationGen(n);
                }

                
foreach (var p in pg)
                {
                    
double u = 1;
                    
for (int i = 0; i < n; i++)
                    { 
//固定行,选列
                        u *= data[i, p[i] - 1];
                    }
                    u 
*= ((SwitchCount(p) & 1== 1 ? -1 : 1);
                    v 
+= u;
                }

                
return v;
            }
        }

        
public class PermutationGen : IEnumerable<int[]>
        {
            
int[] p, t, f;
            
int len;
            StringBuilder pString;

            
public bool ReturnNewPermutation
            {
                
get;
                
set;
            }

            
public bool FastIteration
            {
                
get;
                
set;
            }

            
public PermutationGen(int length)
            {
                len 
= length;
                p 
= new int[length];
                t 
= new int[length];//尚未被使用的数字
                f = new int[length + 1];
                
for (int i = len; i >= 0; i--//最前面两个元素不用
                {
                    f[i] 
= Factorial(i);
                }
            }

            
public int Count
            {
                
get
                {
                    
return f[len];
                }
            }

            
/// <summary>
            
/// 
            
/// </summary>
            
/// <param name="id">1至len</param>
            
/// <returns></returns>
            public int[] GetPermutation(int id)
            {
                
if (id >= f[len] || id < 0throw new ArgumentException("1<=id<=len!");
                
for (int i = 0; i < len; i++//所有数字都未被使用
                {
                    t[i] 
= i + 1;
                }

                
int r, n, m = id;
                
for (int i = 0; i < len; i++)
                {
                    n 
= Math.DivRem(m, f[len - i - 1], out r);
                    p[i] 
= GetUnusedNumberN(n + 1);
                    m 
= r;
                }
                
return p;
            }

            
public string PermutationToString(int[] p)
            {
                
int len = p.Length;
                
if (pString == null)
                {
                    pString 
= new StringBuilder(len * 3);
                }
                pString.Length 
= 0;
                pString.Append(p[
0]);
                
for (int i = 1; i < len; i++)
                {
                    pString.Append(
",");
                    pString.Append(p[i]);
                }

                
return pString.ToString();
            }
            
public string GetPermutationString()
            {
                
return PermutationToString(p);
            }

            
public static int Factorial(int n)
            {
                
int result = 1;
                
for (int i = n; i > 1; i--)
                {
                    result 
*= i;
                }
                
return result;
            }

            
/// <summary>
            
/// 返回第n个未被使用的元素
            
/// </summary>
            
/// <param name="n"></param>
            
/// <returns></returns>
            int GetUnusedNumberN(int n)
            {
                
int count = 0;
                
for (int i = 0; i < len; i++)
                {
                    
if (t[i] != 0)
                    {
                        count
++;
                        
if (count == n)
                        {
                            
int q = t[i];
                            t[i] 
= 0;//返回即被使用
                            return q;
                        }
                    }
                }

                
return 0;//没有足够的剩余元素
            }

            
/// <summary>
            
/// return the smallest positive integer that is not included in the n elements of array starting for start
            
/// </summary>
            int GetNextSmallest(int[] array, int start, int n, int searchStart)
            {
                
int i;
                
for (i = searchStart; i <= searchStart + n; i++)
                {
                    
int j;
                    
for (j = start; j < n; j++)
                    {
                        
if (array[j] == i) break;
                    }
                    
if (j == n)
                    {
                        
return i;
                    }
                }
                
return 0//impossible, but required by grammar
            }

            
#region IEnumerable<int[]> 成员

            
public IEnumerator<int[]> GetEnumerator()
            {
                
if (FastIteration)
                {
                    
for (int i = 0; i < len; i++)
                    {
                        p[i] 
= i + 1;
                    }

                    
for (int i = 0; i < f[len] - 1; i++)//返回第0号到倒数第二个排列
                    {
                        
yield return ReturnNewPermutation ? p.Clone() as int[] : p;
                        
//每次迭代构造下次应当返回的排列
                        for (int j = len - 1; j > 0; j--)
                        {
                            
if (i / f[j] != (i + 1/ f[j])
                            {
                                
//set p at level j
                                int k = len - j - 1;//convert to p index
                                p[k] = GetNextSmallest(p, 0, k, p[k] + 1);
                                k
++;
                                
while (k < len)
                                {
                                    p[k] 
= GetNextSmallest(p, 0, k, 1);
                                    k
++;
                                }
                                
break;
                            }
                        }
                    }
                    
yield return ReturnNewPermutation ? p.Clone() as int[] : p;
                }
                
else
                {
                    
if (ReturnNewPermutation)
                    {
                        
for (int i = 0; i < f[len]; i++)
                        {
                            
yield return GetPermutation(i).Clone() as int[];
                        }
                    }
                    
else
                    {
                        
for (int i = 0; i < f[len]; i++)
                        {
                            
yield return GetPermutation(i);
                        }
                    }
                }
            }

            
#endregion

            
#region IEnumerable 成员

            System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
            {
                
return GetEnumerator();
            }

            
#endregion
        }
    }
}

 

posted on 2010-02-20 11:58  John Rambo  阅读(1446)  评论(1编辑  收藏  举报