全排列產生演算法

來源:互聯網
上載者:User
參考連結: 全排列產生演算法(一)

原文講的很詳細了,為了完整性,這裡粘貼的參考連結中大部分文字,並且在原文的基礎上,添加了“給定某個排列,求其字典序中上一個元素”的演算法。
字典序

全排列產生演算法的一個重要思路,就是將集合A中的元素的排列,與某種順序建立一一映射的關係,按照這種順序,將集合的所有排列全部輸出這種順序需要保證,既可以輸出全部的排列,又不能重複輸出某種排列,或者迴圈輸出一部分排列。字典序就是用此種思想輸出全排列的一種方式這裡以A{1,2,3,4}來說明用字典序輸出全排列的方法。

首先,對於集合A的某種排列所形成的序列,字典序是比較序列大小的一種方式以A{1,2,3,4}為例,其所形成的排列1234<1243,比較的方法是從前到後依次比較兩個序列的對應元素,如果當前位置對應元素相同,則繼續比較下一個位置,直到第一個元素不同的位置為止,元素值大的元素在字典序中就大於元素值小的元素上面的a1[1...4]=1234和a2[1...4]=1243,對於i=1,i=2,兩序列的對應元素相等,但是當i=2時,有a1[2]=3<a2[2]=4,所以1234<1243

求字典序的下一個全排列:使用字典序輸出全排列的思路是,首先輸出字典序最小的排列,然後輸出字典序次小的排列,……,最後輸出字典序最大的排列 這裡就涉及到一個問題,對於一個已知排列,如何求出其字典序中的下一個排列 這裡給出演算法。
  • 對於排列a[1...n],找到所有滿足a[k]<a[k+1](0<k<n-1)的k的最大值,如果這樣的k不存在,則說明當前排列已經是a的所有排列中字典序最大者,所有排列輸出完畢
  • 在a[k+1...n]中,尋找滿足這樣條件的元素l,使得在所有a[l]>a[k]的元素中,a[l]取得最小值。也就是說a[l]>a[k],但是小於所有其他大於a[k]的元素
  • 交換a[l]與a[k].
  • 對於a[k+1...n],反轉該區間內元素的順序。也就是說a[k+1]與a[n]交換,a[k+2]與a[n-1]交換,……,這樣就得到了a[1...n]在字典序中的下一個排列。
這裡我們以排列a[1.. .8]=13876542為例,來解釋一下上述演算法。首先我們發現,1(38)76542,括弧位置是第一處滿足a[k]<a[k+1]的位置,此時k=2 所以我們在a[3...8]的區間內尋找比a[2]=3大的最小元素,找到a[7]=4滿足條件,交換a[2]和a[7]得到新排列14876532,對於此排列的3~8區間,反轉該區間的元素,將a[3]-a[8],a[4]-a[7],a[5]-a[6]分別交換,就得到了13876542字典序的下一個元素14235678
求字典序的上一個全排列:從前面的的分析,我們可以進行逆推導,求得上一個排列,這裡的演算法如下:1. 對於排列a[1..n],從尾端開始,找到第一個a[k]>a[k+1]並記錄,若k<0,則說明a已經是字典序的最小者。2. 在a[k+1..n]中,尋找小於a[k]的最大元素a[i],3. 交換a[k]和a[i]的值,4. 對於a[k+1..n],反轉區間內元素的順序。這裡我們還是以前面的例子來說明,初始時,a=14235678,首先找到1(42)35678,此時k=2,再找到比4小的最大數是3,此時a[i]=3, i=4, 交換a[i]和a[k]的值,得到a=13245678,最後反轉a[k+1..n],得到最後的結果a=13876542。
C代碼如下:
/*http://t.jobdu.com/thread-98707-1-1.html1、寫出一個演算法來產生1-n的全排列2、已知一個長度為N的序列A,它的每個元素是1-N之間的任何一個元素,且兩兩不重複,稱他為一個排列,寫出一個演算法產生該排列的字典序的下一排列。例如,A=[3 2 1 4],則下一排列為A'=[3 2 4 1],A'的下一排列為A''=[3 4 1 2],以此類推。http://blog.csdn.net/joylnwang/article/details/7064115*/#include <stdio.h>void swap(char* array, unsigned int i, unsigned int j){    char t = array[i];    array[i] = array[j];    array[j] = t;}// 遞迴輸出序列的全排列void fullPermutation(char* arr, int len, int index){    int i;    if (index >= len)        printf("%s\n", arr);    else    {        for (i = index; i < len; i++)        {            swap(arr, index, i);            fullPermutation(arr, len, index+1);            swap(arr, index, i);        }    }}void reverse(char arr[], int start, int end){    if (start >= end)        return;    int len = start - end + 1;    int i;    for (i = 0; i <= len/2; i++)    {        swap(arr, start+i, end-i);    }}int pre_permutation(char arr[], int len){    int k, i, max, max_i;    for (i = len-2; i >= 0; i--)    {        if (arr[i] > arr[i+1])        {            k = i;            break;        }    }    if (i < 0)    {        printf("%s is the first permutation\n", arr);        return -1;    }    max_i = k + 1;    max = arr[max_i];    for (i = k+1; i < len; i++)    {        if (arr[i] < arr[k] && arr[i] > max)        {            max_i = i;            max = arr[max_i];        }    }    if (max_i < len)    {        swap(arr, k, max_i);        reverse(arr, k+1, len-1);    }    return 0;}int next_permutation(char arr[], int len){    int k, i, min, min_i;    for (k = len-2; k >= 0; k--)    {        if (arr[k] < arr[k+1])            break;    }    if (k < 0)    {        printf("%s is the last permutation\n", arr);        return -1;    }    min = arr[k+1];    min_i = k+1;    for (i = k + 1; i < len; i++)    {        if (arr[i] > arr[k] && arr[i] < min)        {            min_i = i;            min = arr[i];        }    }    if (min_i < len)    {        swap(arr, k, min_i);        reverse(arr, k+1, len-1);    }    return 0;}int main(){    int i = 1;    char arr[] = "1234";    int len = sizeof(arr) / sizeof(arr[0]) - 1;    //fullPermutation(arr, len, 0); // 遞迴列印全排列    // 按照字典序輸出全排列    printf("next_permutation demo:\n");    do    {        printf("%02d: %s\n", i, arr);        i++;    } while (next_permutation(arr, len) >= 0);    i = 1;    printf("\npre_permutation demo:\n");    do    {        printf("%02d: %s\n", i, arr);        i++;    }    while (pre_permutation(arr, len) >= 0);    return 0;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.