您的位置:首页 > 其它

全排列算法非递归实现和递归实现

2014-02-28 09:26 465 查看
(一)递归的全排列算法

(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)照样可以按照上面的形式进行分解。

[cpp] view
plaincopy

/********************************************************************** 

 * 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的思想。

[cpp] view
plaincopy

/********************************************************************** 

 * 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。

[cpp] view
plaincopy

/********************************************************************** 

 * 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;  

}  

@@@@@@@@

来源:http://blog.csdn.net/hackbuteer1/article/details/6657435

http://plutoblog.iteye.com/blog/976216

http://blog.csdn.net/aipb2008/article/details/2227490
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息