当前位置:首页>编程日记>正文

C++递归与非递归实现全排列

参考文章:http://blog.csdn.net/morewindows/article/details/7370155

http://plutoblog.iteye.com/blog/976216,离散数学及其运用P137

什么是按字典顺序排序的生成排列?

如果在n个正整数集合的两个排列不等的第一个位置,如果一个排列的数小于第二个排列的数,那么这个排列按照字典顺序排在第二个排列的前面

如果要实现按字典顺序生成排列,那么请使用非递归的方法。


//premutation(排列)
//如果要求字典序就用非递归的方法或者直接使用STL中的next_permutation()函数。
//本递归的方法无法实现排列按字典顺序出现
#include "quicksort.h"
int flag=1;//标志位,标记这是第几个


//****************************************************全排列的递归实现
void swap(int *p1,int *p2)
{
int temp=*p1;
*p1=*p2;
*p2=temp;
}
//必须有这个,要排除掉那些重复的排列,去重的全排列就是从第一个数字起每个数分别与它后面非重复出现的数字交换,
//也就是只有第i个数与第j个数交换时,要求[i,j)中没有与第j个数相等的数才交换
bool Isswap(int* num,int start,int end) // start==end或者是start到end没有等于num[end]的值得这两种情况都是可以进行交换的
{
for(int i=start;i<end;i++)
if(num[i]==num[end])
return false;
return true;
}
void allrange(int* num,int k,int m)//全排列的核心思想
{
if(k>m)
cout<<"wrong input"<<endl;
if(k==m)
{
cout<<"第"<<flag<<"个排列";//注意flag标志位必须定义为一个全局变量,不能定义在allrange函数中,否则每次递归flag又从新定义为1了,每次都没有变化
flag++;
for(int i=0;i<=m;i++)//注意数组的输出只能够一次遍历其每一个值
cout<<num[i];
cout<<endl;
}
else
{
for(int i=k;i<=m;i++)
{
if(Isswap(num,k,i))
{
//swap(num+k,num+i);//注意不能够写为swap(num[k],num[i]),要么写成swap(num+k,num+i)
swap(&num[k],&num[i]);
allrange(num,k+1,m);
swap(num+k,num+i);
}
}
}
}


//********************************************************************全排列的非递归实现
//在求字符串的全排列的时候,首先要对字符串进行排序,使得其按升序排序,因为求全排列的算法是按照降序排序的
//这里用快速排序首先处理字符串
void reverse(int *a,int *b)//反转
{
while(a<b)   //这里a,b都是地址,不是值,比如2660,反转后为0662,因为在一开始进行了快排使得序列按照从小到大的顺序排列(升序),
swap(a++,b--);//因为在进行全排列时进行了判断,所以肯定在a到b这段范围内的值都是满足从大到小的顺序,反转后就满足从小到大的顺序,这是生成排列的构造规则
}
bool next_permutation(int num[],int length)
{
//如果不传递length写为length=sizeof(num)/sizeof(int),则实际中求出sizeof(num)为0,因为num是函数的参数。
int *pend=num+length;//超过了位数,比如num有9个,num+9实际是从0到9有十个,所以后面用pend初始化p时要减去1
if(num==pend)
return false;
pend--;
int *p,*q,*pfind;
p=pend;
while(p!=num)
{
q=p;
--p;
if(*p<*q)//生成排列的构造规则,找到降序排列的相邻两个数,前一个数就是要替换掉的数
{
pfind=pend;
while(*pfind<=*p)
--pfind;      //找到第一个大于*p的数,它就是*p之后刚好大于*p的最小的那个数,用它来替换之前找到的那个要替换的数
swap(pfind,p);
//替换后,把q到end的数全部反转,使它们是从小到大排序
reverse(q,pend);
return true;
}
}
reverse(p,pend);//表明此时已经是最大序列了,形如4321,将字符串整个颠倒过来得到最小的排列,并返回false
return false;
}




int main()
{
int num[]={1,3,2,4};
int length=sizeof(num)/sizeof(int);
//allrange(num,0,length-1);
quicksort(num,length,0,length-1);
int k=1;
do{
cout<<"第"<<k++<<"个排列是"<<":";
for(int i=0;i<length;i++)
cout<<num[i]<<" ";
cout<<endl;
}while(next_permutation(num,length));
return 0;
}







http://www.coolblog.cn/news/761d16eeb2de79c4.html

相关文章:

  • asp多表查询并显示_SpringBoot系列(五):SpringBoot整合Mybatis实现多表关联查询
  • s7day2学习记录
  • 【求锤得锤的故事】Redis锁从面试连环炮聊到神仙打架。
  • 矿Spring入门Demo
  • 拼音怎么写_老师:不会写的字用圈代替,看到孩子试卷,网友:人才
  • Linux 实时流量监测(iptraf中文图解)
  • Win10 + Python + GPU版MXNet + VS2015 + RTools + R配置
  • 美颜
  • shell访问php文件夹,Shell获取某目录下所有文件夹的名称
  • 如何优雅的实现 Spring Boot 接口参数加密解密?
  • LeCun亲授的深度学习入门课:从飞行器的发明到卷积神经网络
  • Mac原生Terminal快速登录ssh
  • java受保护的数据与_Javascript类定义语法,私有成员、受保护成员、静态成员等介绍...
  • mysql commit 机制_1024MySQL事物提交机制
  • 支撑微博千亿调用的轻量级RPC框架:Motan
  • jquery 使用小技巧
  • 2019-9
  • 法拉利虚拟学院2010 服务器,法拉利虚拟学院2010
  • vscode pylint 错误_将实际未错误的py库添加到pylint白名单
  • 科学计算工具NumPy(3):ndarray的元素处理
  • 工程师在工作电脑存 64G 不雅文件,被公司开除后索赔 41 万,结果…
  • linux批量创建用户和密码
  • newinsets用法java_Java XYPlot.setInsets方法代碼示例
  • js常用阻止冒泡事件
  • 气泡图在开源监控工具中的应用效果
  • 各类型土地利用图例_划重点!国土空间总体规划——土地利用
  • php 启动服务器监听
  • dubbo简单示例
  • 【设计模式】 模式PK:策略模式VS状态模式
  • [iptables]Redhat 7.2下使用iptables实现NAT
  • Ubuntu13.10:[3]如何开启SSH SERVER服务
  • CSS小技巧——CSS滚动条美化
  • JS实现-页面数据无限加载
  • 阿里巴巴分布式服务框架 Dubbo
  • 最新DOS大全
  • Django View(视图系统)
  • 阿里大鱼.net core 发送短信
  • 程序员入错行怎么办?
  • 两张超级大表join优化
  • 第九天函数
  • Linux软件安装-----apache安装
  • HDU 5988 最小费用流
  • Sorenson Capital:值得投资的 5 种 AI 技术
  • 《看透springmvc源码分析与实践》读书笔记一
  • 正式开课!如何学习相机模型与标定?(单目+双目+鱼眼+深度相机)
  • Arm芯片的新革命在缓缓上演
  • nagios自写插件—check_file
  • python3 错误 Max retries exceeded with url 解决方法
  • 行为模式之Template Method模式
  • 通过Spark进行ALS离线和Stream实时推荐