假設咱們已有6個元素{a,b,c,d,e,f},咱們要將這6個元素的一個序列改爲另外一個序列算法
好比:a b c d e f ide
---> c d f b e a spa
咱們能夠採用「循環記號」標記上面的改變code
(acf)(bd)blog
表示爲a-->c,c-->f,f-->a,b-->d,d-->b排序
在一個排列以後咱們又能夠應用另外一個排序,咱們能夠將兩個排列相乘io
| a b c d e f | | a b c d e f | | a b c d e f |event
| | * | | = | |class
| c d f b e a | | b d c a f e | | c a e b f d |cli
顯然排列乘法不知足交換率,採用循環記號,咱們能夠將上面的乘式寫爲:
(acf)(bd)(abd)(ef)=(acefb)
所以咱們能夠處理多項乘式相乘的結果。
E1.將乘法式中的右括號替換爲與之對應的左括號後一個的字符
E2.從左到右找出沒有被標記過的元素(全部元素都被標記了則算法結束),將該元素賦給Start,輸出左括號以及該元素,並標記該元素
E3.將當前的算式的後一個元素賦給Current
E4.向右掃描算式,若是找到Current的元素,則返回E3.不然掃描至算式末尾
E5.判斷Current==Start,若是不相等,標記Current,找到Current在算式最開始出現的地方.返回E3.
E6.輸出右括號,返回E2
針對每個未標記的元素根據算式遍歷找到最終的替換元素,而後標記該元素,顯然能夠找出全部元素最終替換元素,複雜度爲O(N*L)
void ChangeStr(char *str) { int i; char pre; for(i=0;str[i]!='\0';++i) { if(str[i]=='(') { pre=str[i+1]; } if(str[i]==')') { str[i]=pre; } } } int FindAnyEle(char *src,char *flag,char *start) { int i; for(i=0;src[i]!='\0';++i) { if(src[i]=='(') { continue; } if(!flag[src[i]-'a']) { *start=src[i]; printf("(%c",src[i]); flag[src[i]-'a']=1; return i; } } return -1; } int FindNextEle(char *src,char key,int from) { int i; for(i=from+1;src[i]!='\0';++i) { if(src[i]==key) { return i; } } return -1; } int FindOneEle(char *src,char *flag,char key) { int i; for(i=0;src[i]!='\0';++i) { if(src[i]==key) { printf("%c",key); flag[src[i]-'a']=1; return i; } } return -1; } void PermutationMul(int EleNum,char *SrcMulStr) { ChangeStr(SrcMulStr); char *Flag=(char *)malloc(EleNum*sizeof(char)); int i,id; char Start,Current; for(i=0;i<EleNum;++i) { Flag[i]=0; } id=FindAnyEle(SrcMulStr,Flag,&Start); while(~id) { while(~id) { Current=SrcMulStr[id+1]; id=FindNextEle(SrcMulStr,Current,id+1); } if(Current!=Start) { id=FindOneEle(SrcMulStr,Flag,Current); } else { printf(")"); id=FindAnyEle(SrcMulStr,Flag,&Start); } } free(Flag); printf("\n"); }
E1.初始化,對於1<=i<=N,將T[i]=i;T[i]表示i元素將被T[i]元素替換
E2.從右往左讀取輸入算式,讀取下一個元素,若是輸入結束,算法則也結束,若是元素爲')',置Z=0重複E2;若是爲‘(’,轉去E4,不然轉到E3
E3.交換Z與T[i],若是此時T[i]==0,將i賦值給j;返回E2
E4.將T[j]賦爲Z;返回E2
一遍掃描迭代更新T[i]最終被替換的值,由於咱們要找到最終被替換的值,因此要從右往左讀,若是從左往右讀能夠迭代求出最終替換項被替換的值,好比最終T[1]=3,從右往左讀的話,表示最終1要被3代替,從左往右讀的話,表示最終3是被1代替.
顯然經過逆序迭代每對括號,更新每對括號包含的替換信息,最終能夠求出每一個元素被替代的值,複雜度爲O(L)
void PermutationMulEx(int EleNum,char *SrcMulStr) { int i,j,Z,Len,t; char *T=(char *)malloc(EleNum*sizeof(char)); for(i=0;i<EleNum;++i) { T[i]=i; } Len=strlen(SrcMulStr); for(i=Len-1;i>=0;--i) { if(SrcMulStr[i]==')') { Z=-1; continue; } if(SrcMulStr[i]=='(') { T[j]=Z; } else { t=Z; Z=T[SrcMulStr[i]-'a']; T[SrcMulStr[i]-'a']=t; if(T[SrcMulStr[i]-'a']==-1) { j=SrcMulStr[i]-'a'; } } } for(i=0;i<EleNum;++i) { printf("%d ",T[i]); } printf("\n"); free(T); }