這個說起來太麻煩了, 我找了一個, 你看看行不, 不可以的話, 私聊吧.
創(chuàng)新互聯(lián)公司專注于企業(yè)營銷型網(wǎng)站建設(shè)、網(wǎng)站重做改版、雙柏網(wǎng)站定制設(shè)計、自適應(yīng)品牌網(wǎng)站建設(shè)、H5頁面制作、商城網(wǎng)站開發(fā)、集團(tuán)公司官網(wǎng)建設(shè)、外貿(mào)網(wǎng)站制作、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁設(shè)計等建站業(yè)務(wù),價格優(yōu)惠性價比高,為雙柏等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。
全排列用的是 置換算法,
算法這東西重在理解。具體代碼并不那么重要。
全排列是將一組數(shù)按一定順序進(jìn)行排列,如果這組數(shù)有n個,那么全排列數(shù)為n!個。現(xiàn)以{1, 2, 3, 4, 5}為
例說明如何編寫全排列的遞歸算法。
1、首先看最后兩個數(shù)4, 5。 它們的全排列為4 5和5 4, 即以4開頭的5的全排列和以5開頭的4的全排列。
由于一個數(shù)的全排列就是其本身,從而得到以上結(jié)果。
2、再看后三個數(shù)3, 4, 5。它們的全排列為3 4 5、3 5 4、 4 3 5、 4 5 3、 5 3 4、 5 4 3 六組數(shù)。
即以3開頭的和4,5的全排列的組合、以4開頭的和3,5的全排列的組合和以5開頭的和3,4的全排列的組合.
從而可以推斷,設(shè)一組數(shù)p = {r1, r2, r3, ... ,rn}, 全排列為perm(p),pn = p - {rn}。
因此perm(p) = r1perm(p1), r2perm(p2), r3perm(p3), ... , rnperm(pn)。當(dāng)n = 1時perm(p} = r1。
為了更容易理解,將整組數(shù)中的所有的數(shù)分別與第一個數(shù)交換,這樣就總是在處理后n-1個數(shù)的全排列。
算法如下:
#include stdio.h
int n = 0;
void swap(int *a, int *b)
{
int m;
m = *a;
*a = *b;
*b = m;
}
void perm(int list[], int k, int m)
{
int i;
if(k m)
{
for(i = 0; i = m; i++)
printf("%d ", list[i]);
printf("\n");
n++;
}
else
{
for(i = k; i = m; i++)
{
swap(list[k], list[i]);
perm(list, k + 1, m);
swap(list[k], list[i]);
}
}
}
int main()
{
int list[] = {1, 2, 3, 4, 5};
perm(list, 0, 4);
printf("total:%d\n", n);
return 0;
}
鏈接:
整體思路就是利用回溯的思想,也可認(rèn)為是深度優(yōu)先搜索
從字符串第一位idx=0開始,每次遞歸都從s[idx]之后選擇一個字符與s[idx]交換
因為可能有重復(fù)字符,可使用哈希數(shù)組標(biāo)記當(dāng)前循環(huán)每個字符是否被選擇
因為字符范圍不超過ASCII碼,所以使用128空間的數(shù)組足夠用來標(biāo)記了
選擇好當(dāng)前字符s[i]并與s[idx]交換之后,遞歸調(diào)用繼續(xù)排列下一位s[idx+1]
注意這里要進(jìn)行回溯,即不選s[i]而選擇之后的某個字符交換到s[idx]
所以要將之前的s[i]與s[idx]交換過來,恢復(fù)原狀,才能循環(huán)判斷下一個選擇
具體代碼截圖如下:
運(yùn)行結(jié)果如下:
結(jié)果正確,望采納~
附源碼:
#include stdio.h
#include stdlib.h
#include string.h
#define MAXN 1000000 // 排列總數(shù)可能很多
int num = 0; // 記錄排列總數(shù)
char *res[MAXN] = {NULL}; // 指針數(shù)組保存排列結(jié)果
void swap(char *x, char *y) { // 交換兩個字符變量的內(nèi)容
char ch = *x;
*x = *y;
*y = ch;
}
void perm(char *s, int n, int idx) { // 回溯產(chǎn)生字符串全排列
if (idx == n) { // 已排列到字符串結(jié)尾
? res[num] = (char *)malloc(sizeof(char) * (n + 1));
? //printf("%s\n", s); // 輸出當(dāng)前排列
? strcpy(res[num], s); // 保存當(dāng)前排列
? num++; // 排列總數(shù)加1
? return;
}
int i, hash[128] = {0}; // 哈希數(shù)組,標(biāo)記每個字符是否被選擇
for (i = idx; i n; i++) {
? if (hash[s[i]] == 1)
? ? ? continue; // 跳過已被標(biāo)記過的重復(fù)字符
? hash[s[i]] = 1; // 選過的話在數(shù)組中標(biāo)記為1
? swap(s[idx], s[i]); // 選擇s[i]交換到s[idx]
? perm(s, n, idx + 1); // 遞歸,繼續(xù)s[idx+1]的選擇
? swap(s[idx], s[i]); // 回溯,當(dāng)前不選擇s[i],而選擇其他字符
}
}
int main() {
int n, i;
scanf("%d", n);
char *s = (char *)malloc(sizeof(char) * (n + 1));
scanf("%s", s);
perm(s, n, 0);
printf("一共有%d種排列:\n", num); // 輸出排列總數(shù)
for (i = 0; i num; i++) { // 輸出所有排列
? printf("%s\n", res[i]);
? free(res[i]); // 釋放內(nèi)存空間
}
free(s);
return 0;
}
這其實(shí)是一個遞歸
遞歸函數(shù)
意思是這樣的
比如有n個數(shù)
1
2.。。。n
把1
從第一個開始
往后
與每個數(shù)開始交換
然后
第一個數(shù)就算定了
后面的
第2個到第n個當(dāng)成一個整體
再進(jìn)行這個函數(shù)遞歸
也就是說
第二個到第n個進(jìn)行全排列
這樣下去
當(dāng)全排列到最后一組數(shù)
即第n個數(shù)一個的時候
遞歸退出條件就出來了
就可以輸出全排列的值了
當(dāng)然
最后別忘記把交換的數(shù)還原
再進(jìn)行下一次交換
遞歸哦
所以最后一局的交換也是很重要的
聽完我的解釋
再好好琢磨一下
相信你一定會明白的
要是還是不懂可以繼續(xù)追問我
#include stdio.h
char c,s[10];
int n;
void pern(int k)
{int i;
if(k==n)
printf("%s\n",s+1);
else
for(i=k;i=n;i++)
{c=s[k];s[k]=s[i];s[i]=c;
pern(k+1);
c=s[k];s[k]=s[i];s[i]=c;
}
}
int main()
{ int i;
scanf("%d",n);
for(i=1;i=n;i++)
s[i]='0'+i;
pern(1);
return 0;
}
當(dāng)前名稱:c語言函數(shù)全排列 c語言中的排序函數(shù)
本文地址:http://vcdvsql.cn/article24/dopipce.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供移動網(wǎng)站建設(shè)、網(wǎng)站排名、App開發(fā)、電子商務(wù)、面包屑導(dǎo)航、企業(yè)建站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)