字串的全排列是字串類的演算法題的乙個考察點,屬於普通問題,它有兩種實現方法,遞迴演算法和非遞迴演算法,非遞迴的方法要稍微難一點,以下會依次進行介紹。
演算法思想:求n位的字串的全排列,先確定第0位,然後對後面n-1位進行全排列,在對n-1為進行全排列時,先確定第1位,然後對後面的n-2位進行全排列...由此得到遞迴函式和遞迴的結束條件。全排列也就是交換位置,到n-2位時,就是將n-2和n-1交換位置。
例子:abc,第一位是a固定,對後面的bc交換位置得abc,acb.
當a和b交換位置之後,得到bac,對ac進行全排列bac,bca.
當a和c交換位置之後,得到cba,對ba進行全排列得cba,cab.
根據以上思想編寫**:
1.使用巨集定義來實現兩個字元交換位置(或者自定義乙個交換的函式)
注意:如果是巨集定義接收的引數是字元型別,直接交換位置,因為巨集在引用時,相當於直接把巨集展開插入**中,如果是函式,接收的引數是指標型別。
#define swap(x,y,t) ((t) = (x),(x) = (y),(y) = (t))
main函式,定義乙個字串,需要注意的c語言裡沒有字串,所以只能由字元陣列表示字串。
char
list = "abc";
perm(list, 0, strlen(list)-1);
system("pause");
2.定義全排列的遞迴函式perm(char *list, int i, int n)
int j, temp;
if (i == n)
else
}
結果:
abc的全排列
但是以上演算法會出現乙個問題,比如字串為abb,結果會出錯:
abb的全排列
很明顯以上的結果是不對的,如何改進呢?
出現以上問題的原因,主要是因為相同的字元進行了多次交換。舉個栗子abb,a固定時,後面的字元位置不變,得到abb,當第2個b和第3個b交換時,又得到了abb,解決這個問題的思路在於,在交換時進行判斷,如果後面的字元有重複就不交換。當第i個字元和第j個字元交換位置時,判斷範圍是[i,j)是否有和j重複的數,**如下:
判斷是否交換的函式:
bool isswap(char *list, int
begin, int
end)
return true;
}
改進perm函式:
void
perm
(char *list, int i, int n)
else }}
}
結果:
abb的全排列
首先介紹乙個知識點,替換點和替換數。假設有字串「13421「,我們從字串的最後一位開始掃瞄,找到第一對遞減的字元,在這個例子中,12不是,24不是,43就是了,其中3就是替換數,替換數的位置就是替換點。
演算法思想:先找到替換點,然後從最後一位開始掃瞄,找到比替換數大的最小的數【注意必須是最小的】,交換兩個的位置,然後將替換點後面的數進行逆序,如"421"就逆序成"124"。如此迴圈,得到全排列。
注意:在實現時我們可以先對原來的字串進行排序,這裡使用的是vc庫中的快排函式qsort(),先對字串進行排序的好處在於,找比替換數大的最小的數時處理很方便,因為公升序排序之後,比替換點大的最小的數就是距離替換點最近的數,**中體現在while (pfind <= p)
--pfind;
**如下:
#define swap(x,y,t) ((t) = (x),(x) = (y),(y) = (t))
/*反轉函式*/
void
reverse
(char *a, char *b)
}/*計算下乙個排列*/
bool
nextpermutation
(char
list)
}reverse(p, pend);/*如果沒有下乙個排列,全部反轉*/
return
false;
}int
qsortcmp
(const
void *pa, const
void *pb)
intmain
(void)
while (nextpermutation(list));
system("pause");
return
0;}
結果:
非遞迴-abc的全排列
字串全排列演算法
輸入乙個字串,列印出該字串中字元的所有排列。例如輸入字串abc,則輸出由字元a,b,c所能排列出來的所有字串abc,acb,bac,bca,cab和cba 這是典型的遞迴求解問題,遞迴演算法有四個特性 對於字串的排列問題 如果能生成n 1個元素的全排列,就能生成n個元素的全排列。對於只有乙個元素的集...
演算法 字串全排列演算法
最近在牛客和領扣上刷題,碰到了一些全排列的問題,總結一下。我們首先來看乙個問題?題目 字串的排列 題目描述 輸入乙個字串,按字典序列印出該字串中字元的所有排列。例如輸入字串abc,則列印出由字元a,b,c所能排列出來的所有字串abc,acb,bac,bca,cab和cba。解題思路 使用遞迴的方式來...
演算法學習之字串全排列
第一種方法字串全排列,思想上和我們高中學的排列一樣,比如123,開始的時候第乙個位置有三種選擇,第乙個選完之後第二個位置就只剩下兩種選擇,第三個位置,就剩一種,所以一共有n 種排列,所以我們可以用遞迴的思想去做,遞迴中做交換 include include define max 50 void sw...