當前位置:成語大全網 - 書法字典 - 如何實現C語言中重復元素的全排列?

如何實現C語言中重復元素的全排列?

整個思路就是用回溯的思想,也可以認為是深度優先搜索。

從字符串的第壹個數字idx=0開始,每次遞歸選擇s[idx]之後的壹個字符與s[idx]交換。

因為可能有重復的字符,所以可以使用哈希數組來標記當前循環中的每個字符是否被選中。

因為字符範圍不超過ASCII碼,所以壹個128空間的數組就足夠做標記了。

選擇當前字符s[i]並與s[idx]交換後,遞歸調用繼續排列下壹位s[idx+1]。

註意這裏需要回溯,也就是把選中的字符切換到s[idx]而不是s[i]。

所以要把之前的s[i]和s[idx]互換,恢復到原來的狀態,這樣才能循環判斷下壹個選擇。

具體代碼截圖如下:

運行結果如下:

結果正確,望采納~

附加源代碼:

# include & ltstdio.h & gt

# include & ltstdlib.h & gt

# include & ltstring.h & gt

#define MAXN 1000000 //排列總數可能很大。

int num = 0;//記錄排列總數

char * RES[MAXN]= { NULL };//指針數組保存排列結果。

Void swap(char *x,char *y) {//交換兩個字符變量的內容。

char ch = * x;

* x = * y;

* y = ch

}

Voidperm (char * s,int n,int idx){//回溯生成完整的字符串數組。

If (idx == n) {//已經排列在字符串的末尾。

RES[num]=(char *)malloc(sizeof(char)*(n+1));

//printf("%s\n ",s);//輸出當前排列

strcpy(res[num],s);//保存當前排列

num++;//排列總數加上1

返回;

}

int i,hash[128]= { 0 };//哈希數組,標記每個字符是否被選中。

for(I = idx;我& ltn;i++) {

if (hash[s[i]] == 1)

繼續;//跳過已標記的重復字符。

hash[s[I]]= 1;//如果選中,將在數組中標記為1。

互換(amps[idx],& amps[I]);//選擇s[i]切換到s[idx]

perm(s,n,idx+1);//遞歸地繼續選擇s[idx+1]

互換(amps[idx],& amps[I]);//返回,目前選擇其他字符而不是s[i]。

}

}

int main() {

int n,I;

scanf("%d ",& ampn);

char * s =(char *)malloc(sizeof(char)*(n+1));

scanf("%s ",s);

perm(s,n,0);

Printf("壹個* * *: \n "中有%d個排列),num);//輸出排列總數

for(I = 0;我& ltnumI++) {//輸出所有排列。

printf("%s\n ",RES[I]);

免費(RES[I]);//釋放內存空間

}

免費;

返回0;

}