首先看递归实现,由于递归将问题逐级分解,因此相对比较容易理解,但是需要消耗大量的栈空间,如果线程栈空间不够,那么就运行不下去了,而且函数调用开销也比较大。

(1) 全排列:

全排列表示把集合中元素的所有按照一定的顺序排列起来,使用P(n, n) = n!表示n个元素全排列的个数。

例如:{1, 2, 3}的全排列为:

123;132;

213;231;

312;321;

共6个,即3!=321=6。

这个是怎么算出来的呢?

首先取一个元素,例如取出了1,那么就还剩下{2, 3}。

然后再从剩下的集合中取出一个元素,例如取出2,那么还剩下{3}。

以此类推,把所有可能的情况取一遍,就是全排列了,如图:

知道了这个过程,算法也就写出来了:

将数组看为一个集合,将集合分为两部分:0~s和s~e,其中0~s表示已经选出来的元素,而s~e表示还没有选择的元素。

perm(set,s,e){顺序从s~e中选出一个元素与s交换(即选出一个元素)调用perm(set,s+1,e)直到s>e,即剩余集合已经为空了,输出set}

c语言代码如下:

voidperm(intlist[],ints,inte,void(*cbk)(intlist[])){inti;if(s>e){(*cbk)(list);}else{for(i=s;i<=e;i++){swap(list,s,i);perm(list,s+1,e,cbk);swap(list,s,i);}}}

其中:

voidswap(int*o,inti,intj){inttmp=o[i];o[i]=o[j];o[j]=tmp;}voidcbk_print(int*subs){printf("{");for(inti=0;i

(2)组合:

组合指从n个不同元素中取出m个元素来合成的一个组,这个组内元素没有顺序。使用C(n, k)表示从n个元素中取出k个元素的取法数。

C(n, k) = n! / (k! * (n-k)!)

例如:从{1,2,3,4}中取出2个元素的组合为:

12;13;14;23;24;34

方法是:先从集合中取出一个元素,例如取出1,则剩下{2,3,4}

然后从剩下的集合中取出一个元素,例如取出2

这时12就构成了一个组,如图。

从上面这个过程可以看出,每一次从集合中选出一个元素,然后对剩余的集合(n-1)进行一次k-1组合。

comb(set,subset,n,k){反向从集合中选出一个元素,将这个元素放入subset中。调用comb(set,subset,n-1,k-1)直到只需要选一个元素为止}

C语言代码如下:

voidcombine(ints[],intn,intk,void(*cbk)(int*subset,intk)){if(k==0){cbk(subset,k);return;}for(inti=n;i>=k;i--){subset[k-1]=s[i-1];if(k>1){combine(s,i-1,k-1,cbk);}else{cbk(subset,subset_length);}}}

任何递归算法都可以转换为非递归算法,只要使用一个栈模拟函数调用过程中对参数的保存就行了,当然,这样的方法没有多少意思,在这里就不讲了。下面要说的是用其它思路实现的非递归算法:

(1)全排列:

首先来看一段代码:

#include#includeusingnamespacestd;intmain(){intmyints[]={1,2,3};cout<

这段代码是从STL Permutation上考下来的,要注意的是第10行,首先对数组进行了排序。

第14行的next_permutation()是STL的函数,它的原理是这样的:生成当前列表的下一个相邻的字典序列表,里面的元素只能交换位置,数值不能改变。

什么意思呢?

123的下一个字典序是132,因为132比123大,但是又比其他的序列小。

算法是:

(1) 从右向左,找出第一个比右边数字小的数字A。

(2) 从右向左,找出第一个比A大的数字B。

(3) 交换A和B。

(4) 将A后面的串(不包括A)反转。

就完成了。

好,现在按照上面的思路,写出next_permutation函数:

templateboolnext_perm(T*start,T*end){//_asm{int 3}if(start==end){returnfalse;}else{T*pA=NULL,*pB;T tmp=*end;// find A.for(T*p=end;p>=start;p--){if(*p=start;p--){if(*p>*pA){pB=p;break;}}// swap A, B.tmp=*pA;*pA=*pB;*pB=tmp;// flip sequence after Afor(T*p=pA+1,*q=end;p

(2)组合:01交换法

使用0或1表示集合中的元素是否出现在选出的集合中,因此一个0/1列表即可表示选出哪些元素。

例如:[1 2 3 4 5],选出的元素是[1 2 3]那么列表就是[1 1 1 0 0]。

算法是这样的:

comb(set,n,k){(1)从左到右扫描0/1列表,如果遇到“10”组合,就将它转换为”01”.(2)将上一步找出的“10”组合前面的所有1全部移到set的最左侧。(3)重复(1)(2)直到没有“10”组合出现。}

代码如下:

templatevoidcombine(Tset[],intn,intk,void(*cbk)(Tset[])){unsignedchar*vec=newunsignedchar[n];T*subset=newT[k];// build the 0-1 vector.for(inti=0;i

至于其中的道理,n个位置上有k个1,按照算法移动,可以保证k个1的位置不重复,且覆盖n一遍。

c语言编写排列组合程序,C语言实现排列组合相关推荐

  1. 用c语言编写研究生录取程序,C语言_课程设计---研究生初试录取管理系统.doc

    计算机科学与技术系 课程设计任务书 2010-2011年第二学期 课程 C语言课程设计 课程设计名称 研究生初试录取管理系统 专业班级 10 计本4 指导教师 2011年6月 一. 课程设计目的 将理 ...

  2. C语言编写一下棋程序,C语言编写的与电脑下棋程序代码

    C语言编写的与电脑下棋程序代码 C语言编写的与电脑下棋程序代码 #include "stdafx.h" #include using namespace std; void che ...

  3. c语言找出最大值和最小值并按降序排输出,C语言用排序法给十个数降序排列,用C语言编写,输入10个数按降序排列...

    问题标题 C语言用排序法给十个数降序排列,用C语言编写,输入10个数按降序排列 2019-6-4来自ip:14.161.145.86的网友咨询 浏览量:562 手机版 问题补充: C语言用排序法给十个 ...

  4. c语言字符串dna,转录流程(c语言编写DNA转录程序)

    c语言编写DNA转录程序 AT,CG 进行互换就可以了 #include #include main() { char input[50];/*Defined to store the DNA cod ...

  5. 使用C语言编写测速程序

    可以使用 C 语言编写测速程序.要实现这个功能,你可以使用 C 语言中的时间函数来计算程序运行的时间. 具体来说,可以使用 clock() 函数来计算程序运行的时间.这个函数返回从程序开始运行到调用 ...

  6. 编写程序C语言 用递归法求n,用C语言编写一个递归程序用来计算:1*2+2*3+3*4+.+(n-1)*n...

    用C语言编写一个递归程序用来计算:1*2+2*3+3*4+.+(n-1)*n以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧 ...

  7. 在Linux环境下用C语言编写一个乘法程序mult,从命令行接收两个数字,然后输出其乘积;再用C语言编写一个exec1程序,在程序中使用execvp调用mult程序计算5与10的乘积。

    在Linux环境下用C语言编写一个乘法程序mult,从命令行接收两个数字,然后输出其乘积:再用C语言编写一个exec1程序,在程序中使用execvp调用mult程序计算5与10的乘积. 1.mult. ...

  8. 用C语言编写低耦合程序

    用C语言编写低耦合程序 耦合的定义 低耦合的优点 实现例子 普通的实现方式 低耦合的实现方式 耦合的定义   耦合,是对模块间关联程度的度量. 模块间的耦合度是指模块之间的依赖关系,其耦合性越强,同时 ...

  9. 使用Scala语言编写Spark应用程序实现数据去重

    使用Scala语言编写Spark应用程序实现数据去重 一.题目需求 二.建立目录结构 (一)创建 sparkapp4 文件夹并切换 (二)创建 data 文件夹(存放A.txt B.txt) (三)创 ...

  10. c语言如何自定义运算公式,怎样用C语言编写数学公式 如何用C语言输入数学公式...

    导航:网站首页 > 怎样用C语言编写数学公式 如何用C语言输入数学公式 怎样用C语言编写数学公式 如何用C语言输入数学公式 相关问题: 匿名网友: 1.C语言有现场的常用数学函数,所在函数库为m ...

最新文章

  1. linux 删除含有关键词的文件_误删除Linux系统文件了?这个方法教你解决
  2. 为什么要放弃 Lombok ?
  3. 张一鸣:10年面试2000人,我发现混的好的人,全都有同一个特质!
  4. 如何挑选适合的前端框架(去哪儿网前端架构师司徒正美)
  5. 这款AI语音模型让派大星承认自己是钢铁侠,造假小扎对口型,火到挤爆服务器|在线可玩...
  6. Luogu 2921 [USACO08DEC]在农场万圣节Trick or Treat on the Farm
  7. springmv的执行流程是什么
  8. 数据挖掘实践(金融风控)——task3:特征工程
  9. 微信公众号搜索公众号列表 API
  10. 打开计算机窗口的控制菜单,打开控制面板的几种方法
  11. YOLOv3网络结构细致解析
  12. 1,vue播放视频之—引入.m3u8后缀的hsl视频流
  13. office 2007 word中无法显示嵌入的图片
  14. 西行漫记(16):C#长得太丑了
  15. ThreeJs_投影
  16. 笔记:JavaScript编译与执行
  17. 【服务器】阿里云服务器的初步了解
  18. 神灯搜索软件测试,《没头脑和不高兴》阅读检测及答案
  19. 蚂蚁金服Node.js 基础服务 - 摸爬滚打才不负功名尘土
  20. linux驱动开发扩展--内核启动logo

热门文章

  1. 抖音5×5一笔连线问题无解的证明
  2. 人民搜索副总经理宫玉国离职
  3. 微信强制性诱导分享php,微信公众号运营者注意了,下面这些诱导分享到朋友圈都是不可以的...
  4. 阿里程序员,工作6年,真实薪资曝光
  5. kde下gwenview启动慢,甚至几十秒才能启动
  6. pq分解法matlab编程,基于matlab的pq分解法电力系统潮流计算.pdf
  7. python正确判断错误_python之错误、调试和测试
  8. 怎么批量给文件名加统一的几个字?
  9. Linux基础知识介绍
  10. XP和Linux双系统启动菜单的修复