演算法 字串之全排列

2021-07-28 11:13:31 字數 2674 閱讀 8340

字串的全排列是字串類的演算法題的乙個考察點,屬於普通問題,它有兩種實現方法,遞迴演算法和非遞迴演算法,非遞迴的方法要稍微難一點,以下會依次進行介紹。

演算法思想:求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...