三種求全排列方式之比較


一共有三種求全排列的方式:

第一種就是只適合用於非可重集的DFS實現

第二種就是可以用於可重集上的劉汝佳書上的代碼

第三種就是STL中的next——permutation

 

在對這三種方式做了比較之后發現:

DFS實現的效率最高,當n = 10的時候耗時才不到2s,但是n = 11的時候耗時14s

這是因為在求排列的時候DFS沒有去判斷這個元素在集合中是否重復的出現過,只是直接的去判斷vis數組

第二種方式劉汝佳的實現方式,效率比較的低,甚至不如STL中的next——permuation函數,但是我猜想STL中的實現方式和劉汝佳的差不多

第三種方式使用的時候必須要先把所要求全排列的集合進行排序。

綜上所述:

以后遇到求全排列的時候,如果是非可重集,那么使用DFS(實際上還是一個遞歸的過程,即分治,結合)

如果是可重集,那么直接使用STL

下面附上第一種和第三種的代碼

//STL實現方式
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<ctime>
using namespace std;

const int maxn1 = 100 + 10;
int A1[maxn1];
int main()
{
    for(int i = 1;i <= 10;i++)
    {
        A1[i] = i;

    }
    do
    {
        for(int i = 1;i <= 20;i++)
        {
            printf("%d ",A1[i]);
        }
        printf("\n");
    }while(next_permutation(A1 + 1,A1 + 1 + 10));
    printf("%lf",(double)clock()/CLOCKS_PER_SEC);
    return 0;
}
//有的人把這種實現方式稱作DFS的方式?
//但是DFS雖然是遞歸實現的,但是它在決定下一次遞歸的時候是考慮和當前點的關系的
//所以我更傾向於稱這種方式為遞歸實現的方式
//但是里面還是有很多圖論中的味道的。
#include<cstdio>
#include<cstring>
#include<ctime>
using namespace std;

const int maxn = 100 + 10;
int ans[maxn];
int vis[maxn];
int A2[maxn];
void print_permutation1(int cur ,int n)
{
    if(cur > n)
    {
        for(int i = 1; i <= n;i++)
        {
            printf("%d ",ans[i]);
        }
        printf("\n");
    }
    else for(int i = 1; i <= n;i++)
    {
        if(!vis[i])
        {
            vis[i] = 1;
            ans[cur] = A2[i];
            print_permutation1(cur + 1,n);
            vis[i] = 0;
        }
    }
}

int main()
{
    for(int i = 1;i <= 11;i++)
    {
        A2[i] = i;
    }
    memset(vis,0,sizeof(vis));
    print_permutation1(1,11);
    printf("%lf",(double)clock()/CLOCKS_PER_SEC);
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM