求字符數組的全排列算法

題目:輸入一個字符串,打印出該字符串中字符的所有排列。
例如輸入字符串abc,則輸出由字符a、b、c 所能排列出來的所有字符串abc、acb、bac、bca、cab 和cba。

算法思想
1.把第1個字符換到最前面來(本來就在最前面),準備打印axx,再對後兩個字符b和c做全排列。
2.把第2個字符換到最前面來,準備打印bxx,再對後兩個字符a和c做全排列。
3.把第3個字符換到最前面來,準備打印cxx,再對後兩個字符a和b做全排列。
可見這是一個遞歸的過程,把對整個序列做全排列的問題歸結爲對它的子序列做全排列的問題,注意我沒有描述Base Case怎麼處理,你需要自己想。你的程序要具有通用性,如果改變了N和數組a的定義(比如改成4個數的數組),其它代碼不需要修改就可以做4個數的全排列(共24種排列)。

解題過程
1.當N = 1的時候,則直接打印數列即可。
2.當N = 2的時候,設數組爲 [a, b]
打印a[0], a[1] (即a,b)
交換a[0],a[1]裏面的內容
打印a[0],a[1] (此時已變成了[b, a] )
3.當N = 3的時候,數組爲 [a, b, c]
3.1把a放在 a[0] 的位置(原本也是如此,a[0] = a[0]),打印b,c的全排列(即a[1], a[2]的全排列)
3.2把b放在a[0]的位置(這時候需要交換原數組的a[0]和a[1]),然後打印a, c的全排列,打印完後再換回原來的位置,即a還是恢復到a[0],b還恢復到a[1]的位置
3.3把c放在a[0]的位置(這時候需要交換的是原數組的a[0]和a[2]),然後打印a, b的全排列,打印完後再換回原來的位置,即a還是恢復到a[0],b還恢復到a[1]的位置
至此,全排列完成
當 N = 4,5,6,……的時候,以此類推。

我們可以這麼做:以abc爲例
固定a,求後面bc的排列:abc,acb,求好後,a和b交換,得到bac
固定b,求後面ac的排列:bac,bca,求好後,c放到第一位置,得到cba
固定c,求後面ba的排列:cba,cab。
這裏寫圖片描述

#include <stdio.h>
void print(char * pStr, char * pBegin) {
        if (!pStr || !pBegin)
                return;
        if (*pBegin == '\0')
                printf("%s\n", pStr);
        else {
                for (char * pCh = pBegin; *pCh != '\0'; ++pCh) {
                        char tmp = *pCh;
                        *pCh = *pBegin;
                        *pBegin = tmp;
                        print(pStr, pBegin+1);
                        tmp = *pCh;
                        *pCh = *pBegin;
                        *pBegin = tmp;
                }
        }
}
int main(void) {
        char ch[] = {
                'a', 'b', 'c', '\0'
        };
        print(ch, ch);
        return 0;
}

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章