求一个集合S中m个元素的所有排列以及一个数组A的全排列—递归实现版完整代码

  说明,本文全文代码均用dart语言实现。

  求一个集合S中m个元素的所有排列情况,并打印,非常适合用递归的思路实现。本文给出了两种实现方法,一种是给定的填充排列数组长度是固定的,一种是可变长度的。两种方法主要思路是一样的,只是实现细节上略有差异。具体代码如下:

 1 void permute<E>(Set<E> s, int m) {
 2   if (m < 0 || m > s.length) throw StateError('m is not in [0, ${s.length}]');
 3 
 4   _fill(<E>[], s, m);
 5   print('-------------------');
 6   _fillFixed(List<E>(m), s, 0, m);
 7 }
 8 
 9 10 
11 void _fill<E>(List<E> pm, Set<E> s, int m) {
12   if (pm.length < m) {
13     for (var e in s) {
14       pm.add(e);
15       _fill(pm, _rest(s, e), m);
16     }
17   } else {
18     print(pm);
19   }
20   if (pm.isNotEmpty) pm.removeLast();
21 }
22 
23 void _fillFixed<E>(List<E> pm, Set<E> s, int i, int m) {
24   if (i < m) {
25     for (var e in s) {
26       pm[i] = e;
27       _fillFixed(pm, _rest(s, e), i + 1, m);
28     }
29   } else {
30     print(pm);
31   }
32 }
33 
34 Set _rest<E>(Set<E> s, E e) {
35   var t = s.toSet();
36   t.remove(e);
37   return t;
38 }

 

  如果求一个集合的全排列,如果是集合的话,其实在上面的函数permute,将m的值设为集合s的长度即可:

1 void permuteAll2<E>(Set<E> s) => permute(s, s.length);

  如果求一个数组的全排列情况(假设数组中元素不重合),可以不像集合那样,还需要额外申请空间,直接利用数组本身即可完成:

 1 void permuteAll(List a, int k) {
 2   if (k < a.length - 1) {
 3     for (int i = k; i < a.length; i++) {
 4       if (i != k) _swap(a, k, i);
 5       permuteAll(a, k + 1);
 6       if (i != k) _swap(a, k, i);
 7     }
 8   } else {
 9     print(a);
10   }
11 }
12 
13 void _swap(List a, int i, int j) {
14   var t = a[i];
15   a[i] = a[j];
16   a[j] = t;
17 }

  具体思路,比较简单,直接查看代码即可,或者参照网上的讲解,这里不再赘述了。有兴趣的也可以直接debug,可以看每一步的操作。

  最后,验证代码如下:

1 void main() {
2   var s = {1, 2, 3};
3   permute(s, 3);
4   print('---------------------\n');
5   permuteAll(s.toList(), 0);
6   print('---------------------\n');
7   permuteAll2(s);
8 }

 

posted on 2019-05-13 18:15  Burkut  阅读(479)  评论(0编辑  收藏  举报