generating permunation——全排列(算法汇总)
本文一共提供了4种全排列的方法,包括递归非字典序版本、递归字典序版本、标准库版本和BFS字典序版本,当然BFS非字典序实现相对于BFS字典序版本更加简洁,稍加修改即可。
说明:递归版本基于网上现有代码修改而成,标准库版本参照msdn sample修改而成,最后的BFS版本是由本人在看到题目后思考而来,并实现之(递归版本很久之前写过),所有四种算法都加了模板。当然BFS版本效率相对于递归要快,相对于STL版本则较慢,仅仅提供一种思路而已。
注:对于这种小算法,自己主动思考可以开阔思路,而且想出一种新思路感觉会很不错;对于已成型的经典或者复杂算法,新思路的空间会非常小,所以可以以掌握为主。
/**
@description: generating permunation
@author: seiyagoo
@create: 2013.10.10
@modified: 2013.10.11
**/
- #include <iostream>
- #include <string>
- #include <vector>
- #include <list>
- #include <queue>
- #include <iterator>
- #include <algorithm>
- using namespace std;
- #define MAX 10
- int used[MAX]; //用来标记数字是否已经在前面使用过
- int result[MAX]; //存放结果
- int array[MAX] = {,,,,,,,,,};
- void swap(int x, int y){
- int temp = array[x];
- array[x]=array[y];
- array[y]=temp;
- return;
- }
- template<typename T>
- void printArray(T array[], int size){
- int i;
- for (i=;i<size;i++)
- cout << array[i] << " ";
- cout << endl;
- return;
- }
- /*递归(非字典序)*/
- template<typename T>
- void recur_permute(T array[], int begin, int end)
- {
- int i;
- if (begin==end)
- {
- printArray(array, end+);
- return;
- }
- else{
- //for循环遍历该排列中第一个位置的所有可能情况
- for (i=begin; i<=end; i++){
- swap(begin, i); //循环变换第一个位置
- recur_permute(array, begin+, end); //DFS
- swap(begin, i); //回溯,保持原排列
- }
- }
- }
- /*递归(字典序)*/
- template<typename T>
- void lexi_recur_permute(T array[], int begin, int end)
- {
- int i;
- if (begin == end+)
- {
- printArray(result, end+);
- return;
- }
- else{
- for (i=; i<=end; i++){
- if(!used[i]) //没有标记
- {
- used[i]=; //标记
- result[begin]=array[i]; //记录结果
- lexi_recur_permute(array, begin+, end);
- used[i]=; //回溯
- }
- }
- }
- }
- /*STL(字典序)*/
- template<typename T>
- void stl_permute(T array[], int size)
- {
- vector<T>::iterator begin, end;
- vector<T> Pattern(size) ;
- ostream_iterator<T> out_it(cout, " ") ;
- //int size=sizeof(array)/sizeof(T);
- for(int i=; i<size; i++)
- Pattern[i]=array[i];
- begin = Pattern.begin() ;
- end = Pattern.end() ;
- do
- {
- copy(begin, end, out_it) ;
- cout << endl ;
- }while ( next_permutation(begin, end) );
- }
- int get_factorial(int n)
- {
- if(==n || ==n) return ;
- else return n*get_factorial(n-);
- }
- /*给定元素个数n,以及数组p,返回全排列的序号*/
- template<typename T>
- int perm2num(int n, T *p){
- int i, j, num=,k=;
- for (i=n-;i>=;i--)//注意下标从0开始
- {
- for (j=i+;j<n;j++)
- if (p[j]<p[i]) num+=k;//是否有逆序,如有,统计
- k*=n-i; //每一轮后k=(n-i)!,
- }
- return num;
- }
- /*BFS(字典序)*/
- template<typename T>
- void bfs_permute(T array[], int size)
- {
- int idx=;
- int cnt=get_factorial(size);
- list<T> ls;
- queue<list<T>> q;
- ls.push_back(array[]);
- q.push(ls);
- while(!q.empty())
- {
- list<T> cur_perm = q.front();
- if(cur_perm.size() == size) //第n层的第一个元素长度等于size,循环结束
- break;
- if(cur_perm.size() != idx) //不相等
- idx++;
- q.pop();
- list<T>::iterator it = cur_perm.end();
- while( it!=cur_perm.begin() )
- {
- cur_perm.insert(it, array[idx]); //插入
- q.push(cur_perm);
- it=cur_perm.erase(--it); //还原
- --it; //向前一步找插入点
- if( it==cur_perm.begin() ) //第一个插入点特殊处理并结束
- {
- cur_perm.push_front(array[idx]);
- q.push(cur_perm);
- cur_perm.clear();
- break;
- }
- }
- }
- print_queue(q, size, cnt);
- }
- template<typename T>
- void print_queue(queue<list<T>> q, int size, int cnt)
- {
- vector<list<T>> vec(cnt);
- T* perm=new T[size]; //存储当前排列
- /*映射*/
- while(!q.empty())
- {
- list<T> cur_perm=q.front();
- q.pop();
- list<T>::iterator it=cur_perm.begin();
- int idx=,i=;
- int n=size;
- while(it!=cur_perm.end())
- {
- perm[i++]=*it++;
- }
- //当前排列放入全排列对应位置
- idx=perm2num(size, perm);
- vec[idx]=cur_perm;
- }
- delete []perm;
- /*输出*/
- vector<list<T>>::iterator vit=vec.begin();
- for(;vit!=vec.end();vit++)
- {
- list<T> cur_perm=*vit;
- list<T>::iterator lit=cur_perm.begin();
- for(;lit!=cur_perm.end();lit++)
- {
- cout<<*lit<<" ";
- }
- cout<<endl;
- }
- }
- int main(){
- recur_permute(array, , );
- lexi_recur_permute(array, ,);
- stl_permute(array, );
- bfs_permute(array, );
- return ;
- }
最后再附上STL版本算法思路及修改后的代码(仅仅为了可读性):
思路
- template <class BidirectionalIterator>
- bool next_permutation(BidirectionalIterator first,
- BidirectionalIterator last) {
- BidirectionalIterator i=last;
- if (first == last || first==--i) return false; //单个元素或空则无下一个排列,且使i指向最后一个元素
- for(;;) {
- BidirectionalIterator ii = i--; //i在前,ii在后,循环查找直至*i>=*ii
- if (*i <*ii) { //第一个非降序的元素(即*i)
- BidirectionalIterator j = last;
- while (!(*i <*--j)); //在降序序列[ii,last)中从后往前查找第一个大于*i的数
- iter_swap(i, j); //交换*i,*j,则[ii,last)依然为降序序列
- reverse(ii, last); //翻转[ii,last)为升序
- return true;
- }
- if (i == first) { //没找到连续的两个升序数,则已经是降序序列,直接翻转全部序列
- reverse(first, last);
- return false;
- }
- }
}
generating permunation——全排列(算法汇总)的更多相关文章
- generating permunation
generating permunation——全排列(算法汇总) #include <iostream> #include <string> #include <vec ...
- 排序算法汇总(C/C++实现)
前言: 本人自接触算法近2年以来,在不断学习中越多地发觉各种算法中的美妙.之所以在这方面过多的投入,主要还是基于自身对高级程序设计的热爱,对数学的沉迷.回想一下,先后也曾参加过ACM大大小小的 ...
- 全排列算法的JS实现
问题描述:给定一个字符串,输出该字符串所有排列的可能.如输入“abc”,输出“abc,acb,bca,bac,cab,cba”. 虽然原理很简单,然而我还是折腾了好一会才实现这个算法……这里主要记录的 ...
- 不会全排列算法(Javascript实现),我教你呀!
今天我很郁闷,在实验室凑合睡了一晚,准备白天大干一场,结果一整天就只做出了一道算法题.看来还是经验不足呀,同志仍需努力呀. 算法题目要求是这样的: Return the number of total ...
- 边缘检测matlab算法汇总
边缘检测matlab算法汇总 1. 基于一阶微分算子检测边缘图像 一阶微分边缘算子又称梯度边缘算子,它是利用图像在边缘处的阶跃性,及图像梯度在边缘去得极大值得特征性进行边缘检测. Sobel ...
- JavaScript 数据结构与算法之美 - 十大经典排序算法汇总(图文并茂)
1. 前言 算法为王. 想学好前端,先练好内功,内功不行,就算招式练的再花哨,终究成不了高手:只有内功深厚者,前端之路才会走得更远. 笔者写的 JavaScript 数据结构与算法之美 系列用的语言是 ...
- PHP字符串全排列算法
<?php /** * PHP字符串全排列算法 */ $results = []; $arr = []; function bfs($start) { global $arr; global $ ...
- 全排列算法--递归实现(Java)
求一个n阶行列式,一个比较简单的方法就是使用全排列的方法,那么简述以下全排列算法的递归实现. 首先举一个简单的例子说明算法的原理,既然是递归,首先说明一下出口条件.以[1, 2]为例 首先展示一下主要 ...
- 排列算法汇总(下一个排列,全排列,第K个排列)
一.下一个排列 首先,STL提供了两个用来计算排列组合关系的算法,分别是next_permutation和prev_permutation. next_permutation(nums.begin() ...
随机推荐
- lighttpd启动不了,libssl.so.4&libcrypto.so.4 缺失
lighttd的出错日志在 log/out_lighttpd 里,当lighttd启动不了时候,这里文件中会说明原因. 今天的报错是 error while loading shared librar ...
- 使用gnu automake编译helloworld
使用gnu automake编译helloworld 按照许多介绍automake基本步骤的教程中的说法,我在尝试使用automake编译helloworld示例程序的时候,仍然遇到了几个小坑,所幸后 ...
- JavaScript 实现表格单列按字母排序
<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <title> ...
- 免费的EmBitz可替代Keil MDK开发STM32、NXP项目
一.背景 由于使用之前开发STM32是基于Keil MDK编译环境开发的,由于该软件是收费的,想用个免费开源的软件来替代Keil,EmBitz编译器是免费的,可以完全替代开发.下载程序支持J-Link ...
- 5.Zookeeper的两种安装和配置(Windows):单机模式与集群模式
转自:https://blog.csdn.net/a906998248/article/details/50815031
- [RxJS] How To get the results of two HTTP requests made in sequence
switchMap can chain two HTTP requests together, creating one request based on the results of the fir ...
- cocos2d-x 3.x游戏开发学习笔记(1)--mac下配置cocos2d-x 3.x开发环境
打开用户文件夹下.bash_profile文件,配置环境 vim ~/.bash_profile //按键i,进行插入编辑(假设输错d进行删除一行) 环境配置过程例如以下: 1.首先配置下androi ...
- [D3] Make D3 v4 Charts Responsive with the viewBox attribute
Making SVGs responsive is unfortunately not as simple as adding some media queries. This lesson intr ...
- Linux中IRC通讯工具Pidgin的基本用法
这是我发在南昌大学开源小组里的一篇教程 IRC IRC是个古老的产物,在图形界面流行之前就出现了.可是在现在非常多开源社区都是利用IRC来进行团队交流或对用户提供技术支持的,比方维基百科,所以还是有必 ...
- OpenNI2获取华硕XtionProLive深度图和彩色图并用OpenCV显示
使用OpenNI2打开XtionProLive时有个问题,彩色图分辨率不管怎样设置始终是320*240,深度图倒是能够设成640*480,而OpenNI1.x是能够获取640*480的彩色图的. 彩色 ...