zoukankan      html  css  js  c++  java
  • 转载 求集合笛卡尔积

    最近好像看到好几个集合算法相关的帖子...
    想想把这个文件共享下好了:)

    SetAlgorithms.cs

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



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

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

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

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

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

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


    输出

    Assembly code?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    帽子1,上衣1,裤子a
    帽子1,上衣1,裤子b
    帽子1,上衣2,裤子a
    帽子1,上衣2,裤子b
    帽子1,上衣3,裤子a
    帽子1,上衣3,裤子b
    帽子2,上衣1,裤子a
    帽子2,上衣1,裤子b
    帽子2,上衣2,裤子a
    帽子2,上衣2,裤子b
    帽子2,上衣3,裤子a
    帽子2,上衣3,裤子b
    帽子3,上衣1,裤子a
    帽子3,上衣1,裤子b
    帽子3,上衣2,裤子a
    帽子3,上衣2,裤子b
    帽子3,上衣3,裤子a
    帽子3,上衣3,裤子b



    其余的调用方法也类似.
    举个更实际的例子,例如这帖的问题:
    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 创维 长虹 飞利浦 康佳

    C# code?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    var bands = new string[] { "海尔""LG""三星""索尼""夏普""TCL""创维""长虹""飞利浦""康佳" };
     
                var size = new string[] { "60寸以上""55寸""52寸""50寸""47寸""46寸""42寸" };
     
                var types = new string[] {"IPS硬屏面板""VA面板""ASV面板""黑水晶面板""X-GEN超晶面板" };
     
                var array = new string[][] { bands, size, types };
                SetAlgorithms.CartesianProduct(new int[] { bands.Length + 1, size.Length + 1, types.Length + 1 }, (result, len) =>
                {
                    for (var i = 0; i < array.Length; ++i)
                    {
                        if (result[i] == 0)//跳过"未选"
                            continue;
                        Console.Write("{0} ", array[i][result[i]-1]);
                    }
                    Console.WriteLine();
                    return true;
                });
    这里和大家分享和学习如何学IT!
  • 相关阅读:
    使用 SailingEase WinForm 框架构建复合式应用程序(插件式应用程序)
    SailingEase WinForm 应用程序开发框架
    SailingEase WinForm 框架 DEMO 下载
    SailingEase WinForm 开发框架
    .net动态编译
    VS2010 如何修改程序菜单字体大小?
    Android C++回收机制(转)
    遥测的死区
    发现个开源很好的C++框架库,共享一下
    mongodb查询例子
  • 原文地址:https://www.cnblogs.com/fuchifeng/p/4982412.html
Copyright © 2011-2022 走看看