zoukankan      html  css  js  c++  java
  • 一些集合算法

    转自http://bbs.csdn.net/topics/370006637

    SetAlgorithm.cs

      1 using System;
      2 namespace Rabbit.Tools
      3 {
      4     public static class SetAlgorithms
      5     {
      6         /// <summary>
      7         /// 集合算法的回调
      8         /// </summary>
      9         /// <param name="result">运算结果</param>
     10         /// <param name="length">运算结果有效长度</param>
     11         /// <returns>控制算法是否继续,如果要结束算法,返回false</returns>
     12         /// <remarks>回调中不要修改result中的值,否则可能引起不可预知的后果</remarks>
     13         public delegate bool SetAlgorithmCallback (int[] result,int length);
     14 
     15         //argument check for arrangement and combination
     16         static bool CheckNM(int n, int m)
     17         {
     18             if (m > n || m < 0 || n < 0)
     19                 throw new ArgumentException();
     20 
     21             if (m == 0 || n == 0)
     22                 return false;
     23             return true;
     24         }
     25 
     26         static bool Arrangement(int n, int rlen, int[] result, SetAlgorithmCallback callback)
     27         {
     28             if (rlen == result.Length)
     29                 return callback(result, rlen);
     30 
     31             for (var i = 0; i < n; ++i)
     32             {
     33                 //skip used element
     34                 bool skip = false;
     35                 
     36                 for (var j = 0; j < rlen; ++j)
     37                 {
     38                     if (result[j] == i)
     39                     {
     40                         skip = true;
     41                         break;
     42                     }
     43                 }
     44 
     45                 if (skip)
     46                     continue;
     47                 //set element index
     48                 result[rlen] = i;
     49                 //recurrent next
     50                 if (!Arrangement(n, rlen + 1, result, callback))
     51                     return false;
     52             }
     53             return true;
     54         }
     55         /// <summary>
     56         /// 求排列A(n,m)
     57         /// </summary>
     58         /// <param name="n">集合元素个数</param>
     59         /// <param name="m">取出元素个数</param>
     60         /// <param name="callback">回调</param>
     61         public static void Arrangement(int n, int m, SetAlgorithmCallback callback)
     62         {
     63 
     64             if (!CheckNM(n, m))
     65                 return;
     66 
     67             var result = new int[m];
     68             for (var i = 0; i < n; ++i)
     69             {
     70                 result[0] = i;
     71                 if (!Arrangement(n, 1, result, callback))
     72                     return;
     73             }
     74         }
     75 
     76         static bool Combination(int n,int m, int i, int rlen, int[] result, SetAlgorithmCallback callback)
     77         {
     78             if (rlen == m)
     79                 return callback(result, rlen);
     80 
     81             for (var j = ++i; j < n; ++j)
     82             {
     83                 result[rlen] = j;
     84                 if (!Combination(n,m, j, rlen + 1, result, callback))
     85                     return false;
     86             }
     87             return true;
     88         }
     89         /// <summary>
     90         /// 求组合C(n,m)
     91         /// </summary>
     92         /// <param name="n">集合元素个数</param>
     93         /// <param name="m">取出元素个数</param>
     94         /// <param name="callback">回调</param>
     95         public static void Combination(int n, int m, SetAlgorithmCallback callback)
     96         {
     97             if (!CheckNM(n, m))
     98                 return;
     99 
    100             int[] result;
    101 
    102             result = new int[n];
    103             for (var i = 0; i < n; ++i)
    104             {
    105                 result[0] = i;
    106 
    107                 if (!Combination(n,m, i, 1, result,callback))
    108                     return;
    109             }
    110         }
    111 
    112         static bool SubSet(int n, int i, int rlen, int[] result, SetAlgorithmCallback callback)
    113         {
    114             if (!callback(result, rlen))
    115                 return false;
    116 
    117             if (rlen == n - 1)
    118                 return true;
    119 
    120             for (var j = ++i; j < n; ++j)
    121             {
    122                 result[rlen] = j;
    123                 if (!SubSet(n, j, rlen + 1, result, callback))
    124                     return false;
    125             }
    126             return true;
    127         }
    128         /// <summary>
    129         /// 求除空集外包含n个元素的集合的真子集
    130         /// </summary>
    131         /// <param name="n">集合元素个数</param>
    132         public static void SubSet(int n, SetAlgorithmCallback callback)
    133         {
    134             if (n < 0)
    135                 throw new ArgumentException();
    136             if (n == 0)
    137                 return;
    138 
    139             var result = new int[n - 1];
    140             for (var i = 0; i < n; ++i)
    141             {
    142                 result[0] = i;
    143                 if (!SubSet(n, i, 1, result, callback))
    144                     return;
    145             }
    146         }
    147 
    148         static bool CartesianProduct(int[] sets, int i, int[] result, SetAlgorithmCallback callback)
    149         {
    150             for (var j = 0; j < sets[i]; ++j)
    151             {
    152                 result[i] = j;
    153                 if (i == sets.Length - 1)
    154                 {
    155                     if (!callback(result, result.Length))
    156                         return false;
    157                 }
    158                 else
    159                 {
    160                     if (!CartesianProduct(sets, i + 1, result, callback))
    161                         return false;
    162                 }
    163             }
    164             return true;
    165         }
    166         /// <summary>
    167         /// 求集合笛卡尔积
    168         /// </summary>
    169         /// <param name="sets">包含集合元素个数的数组</param>
    170         /// <param name="callback">回调函数</param>
    171         public static void CartesianProduct(int[] sets, SetAlgorithmCallback callback)
    172         {
    173             int[] result = new int[sets.Length];
    174             CartesianProduct(sets, 0, result, callback);
    175         }
    176     }
    177 }

    提供了以下几个通用的算法:

    求排列  求组合  求集合真子集  求集合笛卡尔积

     没啥技术性,主要是泛用性.

    例如: 已知3个集合 {"帽子1","帽子2","帽子3"}  {"上衣1","上衣2","上衣3"}  {"裤子a","裤子b"}

    求所有的着装组合.可以使用笛卡尔积算法:

    1             var c1= new string[]{"帽子1","帽子2","帽子3"};
    2             var c2 = new string[] { "上衣1", "上衣2", "上衣3" };
    3             var c3 = new string[] { "裤子a", "裤子b" };
    4             SetAlgorithms.CartesianProduct(new int[] { c1.Length, c2.Length, c3.Length }, (result, len) =>
    5             {
    6                 Console.WriteLine("{0},{1},{2}", c1[result[0]], c2[result[1]], c3[result[2]]);
    7                 return true;
    8             });

    其余的调用方法也类似. 举个更实际的例子,例如这帖的问题: http://topic.csdn.net/u/20110527/15/3f9ef827-988c-454c-8bf4-c44f48ec1fa2.html

    例如,商品属性:

     品牌: 海尔 LG 三星 索尼 夏普 TCL 创维 长虹 飞利浦 康佳

     尺寸: 60寸以上 55寸 52寸 5 0寸 47寸 46寸 42寸 

    液晶面板 : IPS硬屏面板 VA面板 ASV面板 黑水晶面板 X-GEN超晶面板

    每个属性都是一个集合,列举出所有筛选可能,包括只选一个条件,现在是3个属性,如果属性个数不确定怎么实现

     对于这个问题.除去有未选的情况,我可以将结果集看做几个集合的笛卡尔集. 那对于未选状态怎么处理呢?我可以人为的为它的头部加上一个"未选"元素.例如品牌就变成了:

    未选 海尔 LG 三星 索尼 夏普 TCL 创维 长虹 飞利浦 康佳

     1 var bands = new string[] { "海尔", "LG", "三星", "索尼", "夏普", "TCL", "创维", "长虹", "飞利浦", "康佳" };
     2 
     3             var size = new string[] { "60寸以上", "55寸", "52寸", "50寸", "47寸", "46寸", "42寸" };
     4 
     5             var types = new string[] {"IPS硬屏面板", "VA面板", "ASV面板", "黑水晶面板", "X-GEN超晶面板" };
     6 
     7             var array = new string[][] { bands, size, types };
     8             SetAlgorithms.CartesianProduct(new int[] { bands.Length + 1, size.Length + 1, types.Length + 1 }, (result, len) =>
     9             {
    10                 for (var i = 0; i < array.Length; ++i)
    11                 {
    12                     if (result[i] == 0)//跳过"未选"
    13                         continue;
    14                     Console.Write("{0} ", array[i][result[i]-1]);
    15                 }
    16                 Console.WriteLine();
    17                 return true;
    18             });
  • 相关阅读:
    C++纯虚函数调用
    C++编译期数据结构 在不同的地方声明全局数组的初始值
    用虚拟机把ubuntu安装到TF卡上
    点击a链接打开第三方页面变成下载页面问题
    SRAM和DRAM的区别
    真值表生成逻辑表达式程序
    大端 小端
    vhdl rising_edge(clk) (clk'event and clk='1')的区别
    ROM、RAM、DRAM、SRAM、FLASH的区别
    同一个主机头的多域名绑定多个ssl证书的方法
  • 原文地址:https://www.cnblogs.com/urwlcm/p/4817124.html
Copyright © 2011-2022 走看看