排列组合 包含求集合笛卡尔积
来源:互联网 发布:杭州最帅交警网络走红 编辑:程序博客网 时间:2024/05/21 17:33
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); } }}提供了以下几个通用的算法:
求排列
求组合
求集合真子集
求集合笛卡尔积
补充对SetAlgorithmCallback 的说明.
关于参数:
这个callback接受两个参数:
result和len.
其中result是生成的结果.
len则是result可用元素的个数.
例如result = {1,2,3,4}
而len = 3.
则只有1 2 3是有效的.
另外result 的值不应该在回调中被修改.否则可能会出错.
关于返回值
SetAlgorithmCallback 返回一个布尔值,用于指示当前的算法是否继续下去.
如果回调函数发现自己需要做的工作已完成,没有必要再计算下去.则可以返回一个false
算法将中断退出.
例如:
已知3个集合
{"帽子1","帽子2","帽子3"}
{"上衣1","上衣2","上衣3"}
{"裤子a","裤子b"}
求所有的着装组合.可以使用笛卡尔积算法:
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; });
输出
帽子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
=========================================================================
其余的调用方法也类似.
举个更实际的例子
例如,商品属性:
品牌: 海尔 LG 三星 索尼 夏普 TCL 创维 长虹 飞利浦 康佳
尺寸: 60寸以上 55寸 52寸 5 0寸 47寸 46寸 42寸
液晶面板 : IPS硬屏面板 VA面板 ASV面板 黑水晶面板 X-GEN超晶面板
每个属性都是一个集合,列举出所有筛选可能,包括只选一个条件,现在是3个属性,如果属性个数不确定怎么实现
对于这个问题.除去有未选的情况,我可以将结果集看做几个集合的笛卡尔集.
那对于未选状态怎么处理呢?我可以人为的为它的头部加上一个"未选"元素.例如品牌就变成了:
未选 海尔 LG 三星 索尼 夏普 TCL 创维 长虹 飞利浦 康佳
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; });
- 排列组合 包含求集合笛卡尔积
- c++求若干个集合的笛卡尔积
- 求笛卡尔积
- Python求笛卡尔积
- 多数组求笛卡尔积
- Python2.7实现笛卡尔积N个数组的排列组合
- 多个集合积-笛卡尔积
- 求笛卡尔积的php代码
- 多个集合做笛卡尔积
- 求排列组合
- 【Python】求笛卡尔乘积
- N个数组中所有元素的排列组合(笛卡尔积)算法
- 【原创】开源.NET排列组合组件KwCombinatorics使用(三)——笛卡尔积组合
- 数据结构和算法数组系列---求数组的笛卡尔积
- php 计算多个集合的笛卡尔积
- php 计算多个集合的笛卡尔积
- php 计算多个集合的笛卡尔积
- 笛卡尔积
- 用py2exe打包成一个exe文件
- golang调用动态库
- 游戏感:虚拟感觉的游戏设计师指南——第八章 环境的测量方法
- 文本替换sed+字段处理cut,join+awk重新编排字段
- 范式
- 排列组合 包含求集合笛卡尔积
- linux设备模型 底层
- 微软100题(87)最大连续递增数字串
- C++ - C++0x/C++11 Support in GCC
- 获得Properties文件的内容
- iOS开发工具——网络封包分析工具Charles
- 游戏感:虚拟感觉的游戏设计师指南——第九章 润色的测量方法
- 滑动返回上一层级
- ubuntu14.04下配置使用openCV3.0