全排序的递归与非递归的实现
来源:互联网 发布:引物分析软件 编辑:程序博客网 时间:2024/05/28 15:06
(一)递归的全排列算法
(A、B、C、D)的全排列为
1、A后面跟(B、C、D)的全排列
2、B后面跟(A、C、D)的全排列
3、C后面跟(A、B、D)的全排列
4、D后面跟(A、B、C)的全排列
而对1中的(B、C、D)照样可以按照上面的形式进行分解。
- /**********************************************************************
- * Compiler: GCC
- * Last Update: Mon 07 May 2012 07:08:58 PM CST
- * File Name: 1.cpp
- * Description: 利用stl中的next_permutation进行全排列
- ************************************************************************/
- #include <iostream>
- using namespace std;
- template<typename T>
- void permutation(T array[], int begin, int end)
- {
- int i;
- if(begin == end){
- for(i = 0; i <= end; ++i){
- cout<<array[i]<<" ";
- }
- cout<<endl;
- return;
- } else {
- //for循环遍历该排列中第一个位置的所有可能情况
- for(i = begin; i <= end; ++i) {
- swap(array[i], array[begin]);
- permutation(array, begin + 1, end);
- swap(array[i], array[begin]);
- }
- }
- }
- int main(int argc, char **argv)
- {
- int a[4] = {1, 2, 3, 4};
- permutation(a, 0, sizeof(a) / sizeof(int) - 1);
- return 0;
- }
(二)非递归全排列算法,即按字典序排列算法。
基本思想是:1.对初始队列进行排序,找到所有排列中最小的一个排列Pmin。
2.找到刚刚好比Pmin大比其它都小的排列P(min+1)。
3.循环执行第二步,直到找到一个最大的排列,算法结束。
如排列ABCDE,这是所有排列中最小的一个排列,刚好比ABCDE大的排列是:ABCED。
算法如下:
给定已知序列P = A1A2A3.....An
对P按字典排序,得到P的一个最小排列Pmin = A1A2A3....An ,满足Ai > A(i-1) (1 < i <= n)
从Pmin开始,找到刚好比Pmin大的一个排列P(min+1),再找到刚好比P(min+1)大的一个排列,如此重复。
1.从后向前(即从An->A1),找到第一对为升序的相邻元素,即Ai < A(i+1)。
若找不到这样的Ai,说明已经找到最后一个全排列,可以返回了。
2.从后向前,找到第一个比Ai大的数Aj,交换Ai和Aj。
3.将排列中A(i+1)A(i+2)....An这个序列的数逆序倒置,即An.....A(i+2)A(i+1)。因为由前面第1、2可以得知,A(i+1)>=A(i+2)>=.....>=An,这为一个升序序列,应将该序列逆序倒置,所得到的新排列才刚刚好比上个排列大。
4.重复步骤1-3,直到返回。
这个算法是C++ STL算法next_permutation的思想。
- /**********************************************************************
- * Compiler: GCC
- * Last Update: Mon 07 May 2012 07:08:58 PM CST
- * File Name: 1.cpp
- * Description:
- ************************************************************************/
- #include <iostream>
- #include <cstring>
- using namespace std;
- //交换数组a中下标为i和j的两个元素的值
- void swap(int *a,int i,int j)
- {
- a[i]^=a[j];
- a[j]^=a[i];
- a[i]^=a[j];
- }
- //将数组a中的下标i到下标j之间的所有元素逆序倒置
- void reverse(int a[],int i,int j)
- {
- for(; i<j; ++i,--j) {
- swap(a,i,j);
- }
- }
- void print(int a[],int length)
- {
- for(int i=0; i<length; ++i)
- cout<<a[i]<<" ";
- cout<<endl;
- }
- //求取全排列,打印结果
- void combination(int a[],int length)
- {
- if(length<2) return;
- bool end=false;
- while(true) {
- print(a,length);
- int i,j;
- //找到不符合趋势的元素的下标i
- for(i=length-2; i>=0; --i) {
- if(a[i]<a[i+1]) break;
- else if(i==0) return;
- }
- for(j=length-1; j>i; --j) {
- if(a[j]>a[i]) break;
- }
- swap(a,i,j);
- reverse(a,i+1,length-1);
- }
- }
- int main(int argc, char **argv)
- {
- int a[4] = {1, 2, 3, 4};
- combination(a, sizeof(a) / sizeof(int));
- return 0;
- }
用STL实现:
STL有一个函数next_permutation(),它的作用是如果对于一个序列,存在按照字典排序后这个排列的下一个排列,那么就返回true且产生这个排列,否则返回false。
- /**********************************************************************
- * Compiler: GCC
- * Last Update: Mon 07 May 2012 07:08:58 PM CST
- * File Name: 1.cpp
- * Description: 利用stl中的next_permutation进行全排列
- ************************************************************************/
- #include <iostream>
- #include <algorithm>
- using namespace std;
- template <typename BidirectionalIterator>
- void permutation(BidirectionalIterator array, int len)
- {
- sort(array, array + len);
- do{
- for(int i = 0; i < len; ++i){
- cout<<array[i]<<" ";
- }
- cout<<endl;
- }while(next_permutation(array, array + len));
- }
- int main(int argc, char **argv)
- {
- int a[4] = {1, 2, 3, 4};
- permutation(a, sizeof(a) / sizeof(int));
- return 0;
- }
- 全排序的递归与非递归的实现
- 全排列的递归实现与非递归实现
- 全排列算法的递归与非递归实现
- 全排列算法的递归与非递归实现
- 全排列的递归与非递归实现
- 全排列算法的递归与非递归实现
- 全排列的递归与非递归算法实现
- 全排列的递归与非递归实现
- 全排列的递归与非递归实现
- 全排列的递归与非递归
- 归并排序的递归实现与非递归实现
- 归并排序的递归实现与非递归实现
- 快速排序的递归与非递归实现
- 直接插入排序的递归与非递归实现
- 归并排序递归与非递归的实现
- 归并排序(递归与非递归)的实现
- 链表归并排序的递归与非递归实现
- 归并排序的递归与非递归实现Java
- 自定义控件(自定义窗口)在对话框中接收不到WM_CHAR消息的解决方法
- 理解Fragment生命周期
- Spring 源码阅读(1)
- android usb host 读写USB设备
- POJ 3498 - March of the Penguins 拆点构图最大流
- 全排序的递归与非递归的实现
- HDU 3607 Traversal (线段树)
- Android USB 主机模式
- oracle查询审计信息
- 一、体系结构以及基本概念
- printf 十六进制格式化输出 2字节对齐
- Ubuntu下的android NDK 环境搭建
- android 自动检测版本升级
- C++ 中的流操作