基于C#程序设计语言的三种组合算法
基于C#程序设计语言的三种组合算法
1. 总体思路
1.1 前言
最近有个项目要求对多种材料进行装箱,我需要给出装箱的可能,这些材料进行过分组,每组中大致选取2-3个材料进行装箱。由于无法得知箱子大小(无法对组合数的m进行限制),材料会扩充,随之分组也会扩充(无法对组合数的n进行限制),所以理论上说能产生的组合是无限的,这当然无法实现,但我们还是能通过用户的输入来进行最大可能的处理。
1.2 算法思路
组合算法思路是比较简单的(以下所有数据都可以想象成string[]类型的),获取源数据S,C(1,n)的结果S1,将S的每个元素与S1进行相应组合得到C(2,n)的结果S2(思路演示见图1.2.1),S2,将S的每个元素与S2进行相应组合,得到S3...重复这个过程得到Sn。
S的元素与Si进行组合的方式不同获得的组合结果不同,如果和元素本身进行了组合,组合结果就包括了与自身组合。

图1.1 C(2, n)组合过程
1.3 算法需要注意的点
虽然思路比较简单,但是处理起来还是有些地方需要注意。在每次进行组合时,需要对Si进行去头处理。
去头处理:去掉Si中不能与S[i]组合的元素
在不同的组合中去掉的头也不同。在与S1组合时,每次去掉的只有一组元素[A],[B],[C],[D],[E],但在与S2组合时,去掉的头分别是:[A,B],[A,C],[A,D],[A,E](4组),[B,C],[B,D],[B,E](3组),[C,D],[C,E](2组),[D,E](1组)。推过推演可以发现,这组数据是有规律的,根据1.2,1.3小节总结出来的规律,大致可以构建出组合算法了。
2. 三种组合算法
2.1 普通组合算法
在第1章已经介绍了普通组合算法的思路,这里主要说明如何用C#代码来处理组合运算,首先需要定义三个List<string>类型src,res,tmp,src用来存储需要进行组合处理的源数据,res用来存储组合处理后的数据,tmp用来存储在操作过程中的临时数据。定义一个int[] rm变量用来存储每次需要去头的个数(例如src=[A,B,C,D,E],进行第一次组合时,rm = [1,1,1,1], 进行第二次组合时,rm = [4,3,2,1])。
string[] Combination(List<string> src, List<string> res, List<string> tmp, ref int[] rm, int rsp, int tmp_index, int rp)
{
if(res.Count() == 0)
{
return tmp;
}
if(rsp == res.Count())
{
src.Removerange(0, 1);
res.Removerange(0, rm[rp]);
rm[rp] = rsp;
rsp = 0;
rp += 1;
}
tmp[tmp_index] = src[0] + "," + res[rsp];
tmp = Combination(src, res, tmp, rm, rsp + 1, tmp_index + 1, rp);
return tmp;
}
代码清单2.1 普通组合算法
2.2 与自身进行组合的组合算法
本节思路及代码与2.1小节大同小异,故先略过。
2.3 组合元素进行过分组限制的组合算法
现在要求将元素进行分组,每组的元素个数随机,从每组最多选择x个元素进行组合。这种算法只需要在普通组合算法程序中进行一些条件限制便可以实现,最主要需要注意的问题是,rm中存储的数据不同了(对下次去掉的头有了限制)。由于rm[rp]不再是rsp了,所以需要新的变量count来计算下次需要去掉的头。
string[] Combination(List<string> src, List<string> res, List<string> tmp, ref int[] rm, int rsp, int tmp_index, int rp, int count)
{
if(res.Count() == 0)
{
return tmp;
}
if(rsp == res.Count())
{
src.Removerange(0, 1);
res.Removerange(0, rm[rp]);
rm[rp] = count;
rsp = 0;
rp += 1;
}
// ...
// 检测是否属于同一分组,如果属于同一分组,则bool bl = true;
// ...
if(bl == true)
tmp = Combination(src, res, tmp, rm, rsp + 1, tmp_index + 1, rp);
else
{
tmp[tmp_index] = src[0] + "," + res[rsp];
count++;
}
return tmp;
}
代码清单2.2 有分组限制的组合算法
代码清单2.2中,省略了“检测是否属于同一分组”的代码,因为不同需求的初始条件不一样,故略过了此段代码。在我涉及到的需求中,我是将分组内容用DataTable存储,然后“检测同一分组”时会去表中检索,以此来判断是否属于同一分组。对于检测,我将所需要检测的内容组合成一个数组,然后检测首元素是否与指向元素属于同一分组,如果属于,bool bl为true,如果不属于,则为false。
我将所需要检测的内容组合成一个数组,然后定义两个指针(索引)pa,pb,pa与pb初始都指向首元素,若pa内容与pb内容相等,则count++,若pa内容与pb内容不等,则pa = pb + 1,再重复上述步骤,这样可以统计出一个组内包含多少个成员。
3. 请使用循环替代递归
最后,请使用循环来带起递归过程,因为递归未结束时,是不会释放内存的,在数据量大时,会造成内存溢出的错误,所以,请使用循环。
PS: 本文所涉及的代码均未经过编译,若出现错误请进行修改。
基于C#程序设计语言的三种组合算法的更多相关文章
- js架构设计模式——你对MVC、MVP、MVVM 三种组合模式分别有什么样的理解?
你对MVC.MVP.MVVM 三种组合模式分别有什么样的理解? MVC(Model-View-Controller)MVP(Model-View-Presenter)MVVM(Model-View-V ...
- ASP.NET MVC:多语言的三种技术处理策略
ASP.NET MVC:多语言的三种技术处理策略 背景 本文介绍了多语言的三种技术处理策略,每种策略对应一种场景,这三种场景是: 多语言资源信息只被.NET使用. 多语言资源信息只被Javascrip ...
- 第二百五十九节,Tornado框架-模板语言的三种方式
Tornado框架-模板语言的三种方式 模板语言就是可以在html页面,接收逻辑处理的self.render()方法传输的变量,将数据渲染到对应的地方 一.接收值渲染 {{...}}接收self.re ...
- 排序—时间复杂度为O(n2)的三种排序算法
1 如何评价.分析一个排序算法? 很多语言.数据库都已经封装了关于排序算法的实现代码.所以我们学习排序算法目的更多的不是为了去实现这些代码,而是灵活的应用这些算法和解决更为复杂的问题,所以更重要的是学 ...
- FIFO、LRU、OPT这三种置换算法的缺页次数
考虑下述页面走向: 1,2,3,4,2,1,5,6,2,1,2,3,7,6,3,2,1,2,3,6 当内存块数量分别为3时,试问FIFO.LRU.OPT这三种置换算法的缺页次数各是多少? 答:缺页定义 ...
- 网络中,FIFO、LRU、OPT这三种置换算法的缺页次数
FIFO.LRU.OPT这三种置换算法的缺页次数 转载 由于要考计算机四级网络,这里遇到了问题,就搜了一些资料来解疑. 考虑下述页面走向: 1,2,3,4,2,1,5,6,2,1,2,3,7,6,3 ...
- 三种Hash算法对比以及秒传原理.
三种Hash算法对比以及秒传原理 CRC (32/64) MD5 Sha1 分5个点来说 1.校验值长度 2.校验值类别 3.安全级别 4.应用场景 1).校验值长度 CRC(32/64) 分别 ...
- 创建B树,动态添加节点,并使用三种遍历算法对树进行遍历
ks17:algorithm apple$ cat btree_test.c ///********************************************************** ...
- c++ 指针与const的三种组合
三种形式 const int a=1; int b=2: 1 const int * ptr1=&a; 2 int * const ptr2 = b; 3 const int * const ...
随机推荐
- 在浏览器输入URL时发生了什么
浏览器器检查cache,如果请求对象已经缓存并且是最新的,执行第9步. 浏览器询问操作系统,请求服务器的IP地址 操作系统进行DNS查找,然后告诉浏览器服务器的IP 浏览器和服务器简历一个TCP连接( ...
- ES6新增的常用数组方法(forEach,map,filter,every,some)
ES6新增的常用数组方法 let arr = [1, 2, 3, 2, 1]; 一 forEach => 遍历数组 arr.forEach((v, i) => { console.log( ...
- Nginx的gzip
webpack compression-webpack-plugin => .gz CompressionPlugin = require("compression-webpack- ...
- String类,StringBuffer类转字符数组
String不可变类型和StringBuffer可变类型 String类和StringBuffer类都是字符串表示类,区别在于String对象引用变量是不可变的,而StringBuffer类对象引用变 ...
- 微信小程序ios点击状态栏返回顶部不好使
最近做了一款微信小程序,各方面感觉都很完美(萝卜一直这么自信),今天设计总监告诉我你的小程序怎么返回顶部不好使呀,吓得我赶紧拿手机试试,没毛病啊,我手机(苦逼的安卓机)上点两下就回去了呀,遂去找他理论 ...
- Servlet, Struts2和SpringMVC 并发访问线程安全问题
第一部分: Servlet不是线程安全的. 要解释Servlet为什么不是线程安全的,需要了解Servlet容器(即Tomcat)使如何响应HTTP请求的. 当Tomcat接收到Client的HTTP ...
- WordPress外链新窗口打开并使用php页面go跳转
之前浏览别人的博客网站,打开外链时会有一个等待时间的代码,虽然不知道有什么用,但觉的挺有档次..今天正好看到教程,就自己也加上了,就复制粘贴些代码可以了 首先创建一个php文件,名字随便,如果你不想改 ...
- IDEA使用Maven搭建SSM框架
搭建环境:Intellij IDEA 2017 JDK 1.8 Tomcat 8.5 MySQL 5.7 Spring 4.x Mybatis 3.x 这个过程确实太麻烦了,我用了两个小时 所以建议用 ...
- [Swift]LeetCode593. 有效的正方形 | Valid Square
Given the coordinates of four points in 2D space, return whether the four points could construct a s ...
- [Swift]LeetCode713. 乘积小于K的子数组 | Subarray Product Less Than K
Your are given an array of positive integers nums. Count and print the number of (contiguous) subarr ...