全排列的遞迴與非遞迴

2021-07-07 05:36:10 字數 1752 閱讀 4756

全排列是乙個十分基礎的概念,是一串有可比權值的元素出現的所有排列形式,例如 '張全蛋'、'張蛋全'、'全張蛋'、'全蛋

張'、'蛋全張'、'蛋張全'就是張全蛋的全排列,所以我們發現全排列用來取名字是很不錯的,如果對每個漢字在名字中的權值做一

張表,再來一張可能出現的不同字同時出現在名字中的關聯權值表,那麼全排列可以算出一張取名字的優先表,暫不表。

那麼全排列基本的乙個規律我們可以很明顯的發現,乙個元素集合的全排列可以由該集合u內任意元素a加上剔除該元素後的集合

u的全排列組成,而集合u也可以使用該方式去求全排,而最後不可細分的集合就是乙個元素。這個描述很適合由遞迴來做,拿'張全

蛋'來說,它的全排列由:

'張'+'全蛋'的全排 '全'+'張蛋'的全排 '蛋'+'張全'的全排

簡而言之 由集合u中每個元素與u的第乙個元素交換位置後,剩餘的元素集合u遞迴去做該操作,直到u中只剩1個元素時(即遞迴

到集合最後乙個元素時)輸出乙個排列,最終得到集合u全排列。

//求集合u的全排遞迴實現 

//all-s的值即為剩餘元素集合u的大小

//s即為u集合的起點位置,起始位置為0

void allsorts(char u,int s,int all)else

}}void swaps(char s,int i,int j)

第二種方式是用非遞迴的方法去操作,對於'1234'來說全排列按照字典序'1234'的下乙個排列為'1243',最後一種排

為'4321',權值越大的元素在高位的排列應該越靠後,那麼如果要靠生成的方法去列印出每乙個排列,如果出現權值大的元素

出現在序列的後部,將其向前放,再將該元素後的元素列翻轉可以得到該排列的下乙個排列。如求'23154'的後乙個排列,從

右往左第一次出現遞減的位置是 5>1 ,那麼將1這個位置標記為待替換的位置m,在從右往左遍歷第乙個大於1的數字為4,那

麼交換1,4後有'23451',再將位置m後的串翻轉有'23415'。按照這種方式可以列印出整個全排列

//非遞迴求u的全排列,l為u中元素個數

void allsort(char u,int l)else

if(i==0)

}for(int j=l-1;j>i;j--)

}

}//交換i,j位置的

void swaps(char s,int i,int j)

//翻轉i-j

void resevert(char s,int i,int j)

char b = a[s];

int m = s,ss=s,ee=e;

while(sfor(;e>=s;e--)

}for(;s<=e;s++)}}

a[m] = b;

qsorts(a,ss,m-1);

qsorts(a,m+1,ee);

}bool isswaped(char s,int i,int j)

}return

true;

}void swaps(char s,int i,int j)

//遞迴全排列

void quanpai1(char s,int st,int ed)else

}

}}int main()

}

除了取名字的腦洞之外,全排列貌似用來做彩票開獎**是比較多的~~~~~~

全排列 遞迴與非遞迴實現

全排列問題在公司筆試的時候非經常見,這裡介紹其遞迴與非遞迴實現。簡單地說 就是第乙個數分別以後面的數進行交換 e.g e a b c 則 prem e a.perm b,c b.perm a,c c.perm a,b 然後a.perm b,c ab.perm c ac.perm b abc acb....

全排列的遞迴與非遞迴實現

1 全排列 將n個不同元素按照不同的順序進行排列,一般要求所有的排列方式,或者滿足某些要求的排列方式,比如先後順序的限制 2 遞迴實現全排列 eg 對 a b c d 進行全排列,可以按照以下的步驟 1.a後面加上 b c d 的全排列 2.b後面加上 a c d 的全排列 3.c後面加上 b a ...

全排列的遞迴與非遞迴實現

問題 輸入乙個序列 元素無重複 輸出其全排列 一般採用經典的遞迴解法,後來想將其改造為非遞迴 思考很久後覺得並不好寫,手工模擬遞迴棧的行為容易出錯。然後上網搜尋了一下眾的非遞迴 發現很多人的非遞迴 是各種全新的求解演算法,而不是相同演算法的非遞迴實現,和我想要的不一樣。遞迴解法 假設輸入序列 0,1...