字符串的全排列非递归算法是每次都寻找比前序列大一点的序列,如:
起点:字典序最小的排列,例如12345
终点:字典序最大的排列,例如54321
过程:从当前排列生成字典序刚好比它大的下一个排列。
算法过程:后找、小大、交换、翻转
后找:字符串中最后一个升序的位置i,即S[k]>S[k+1](k>i),S[i]<S[i+1];
查找(小大):S[i+1...N-1]中比Ai大的最小值Sj;
交换:Si,Sj;
翻转:S[i+1...N-1]
代码如下:
1 #include2 #include 3 using namespace std; 4 5 //交换 6 void swap(char &c1, char &c2) 7 { 8 char temp = c1; 9 c1 = c2; 10 c2 = temp; 11 } 12 13 //翻转 14 void reverse_string(string &str, int from, int to) 15 { 16 while(from < to) 17 { 18 swap(str[from++], str[to--]); 19 } 20 } 21 22 //找最小值的下标 23 int Find_min(string str, int from, int to) 24 { 25 char min = str[from]; 26 int j = from; 27 if(from == to) 28 { 29 return j; 30 } 31 for(int i = from + 1; i <= to; ++i) 32 { 33 //查找比str[from - 1]大的最小值 34 if(str[i] <= min && str[i] > str[from - 1]) 35 { 36 min = str[i]; 37 j = i; 38 } 39 } 40 return j; 41 } 42 43 void permutation_2(string &str, int from, int to) 44 { 45 string end_str(str); 46 reverse_string(end_str, from, to); 47 cout << str << endl; 48 while(str != end_str) 49 { 50 int i = from; 51 int j = to; 52 while(i != j) 53 { 54 if(str[j -1] < str[j]) 55 { 56 break; 57 } 58 j--; 59 } 60 int min = Find_min(str, j, to); 61 swap(str[j-1], str[min]); 62 reverse_string(str, j, to); 63 cout << str << endl; 64 } 65 //把str翻转回来 66 reverse_string(str, from, to); 67 } 68 69 int main(int argc, const char *argv[]) 70 { 71 string str = "1223"; 72 int len = str.size(); 73 permutation_2(str, 0, len - 1); 74 return 0; 75 }
结果:
注意:C++STL已经在Algorithm中集成了next_permutation。可以将给定的字符串A[0...N-1]首先升序排序,然后依次调用next_permutation直到返回false,即完成了非递归的全排列算法。