- UID
- 6266
- 精华
- 积分
- 794
- 威望
- 点
- 宅币
- 个
- 贡献
- 次
- 宅之契约
- 份
- 最后登录
- 1970-1-1
- 在线时间
- 小时
|
本帖最后由 usr 于 2021-3-23 13:11 编辑
这篇帖子主要介绍一种排列生成算法,这种算法不同于C++ STL库中的排列生成算法。
读者可以自行分析它的效率。
- #include <iostream>
- #include <algorithm>
- using namespace std;
- template <class T>
- class CIntPair
- {
- public:
- static constexpr bool LEFT = false;
- static constexpr bool RIGHT = true;
- bool direction = LEFT;
- T value = 0;
- };
- template <class T>
- class CArrangement
- {
- private:
- class CRtn
- {
- public:
- bool found;
- CIntPair<T> pair;
- size_t index;
- CRtn(size_t i, CIntPair<T> & p) : pair(p), index(i), found(false) {}
- };
- size_t n;
- unsigned long long counter = 1;
- CIntPair<T> * arr;
- // Function: MaxMovableIndex
- // Description:
- // A number(CIntPair) is movable, only if the adjacent number that the direction of the movable number pointed is less than
- // the removable number.
- // Therefor this procedure is to find the maximum number of all removable numbers.
- // If there were the maximun number exist, permutation would be able to go on, otherwise there wouldn't be the next permuatation.
- // And CRtn().found shows whether we could find the max movable number.
- // Simultaneously, CRtn().index stores the index of removable number, CRtn().pair stores the movable number itself then.
- CRtn MaxMovableIndex()
- {
- size_t i;
- CIntPair<T> t;
- CRtn r(0, t);
- for (i = 0; i < n; ++i)
- {
- if (arr[i].direction == CIntPair<T>::LEFT)
- {
- if (i > 0 && arr[i - 1].value < arr[i].value && r.pair.value < arr[i].value)
- {
- r.pair = arr[i];
- r.index = i;
- r.found = true;
- }
- }
- else
- {
- if (i < n - 1 && arr[i + 1].value < arr[i].value && r.pair.value < arr[i].value)
- {
- r.pair = arr[i];
- r.index = i;
- r.found = true;
- }
- }
- }
- return r;
- }
- // Function: Swap
- // Description: Swap two adjacent numbers by index and direction.
- void Swap(size_t i)
- {
- if (arr[i].direction == CIntPair<T>::LEFT)
- swap(arr[i], arr[i - 1]);
- else
- swap(arr[i], arr[i + 1]);
- }
- // Function: ChangeDirection
- // Description: Change all directions which belong to p, such that p > r.pair.value.
- void ChangeDirection(CRtn & r)
- {
- size_t i;
- for (i = 0; i < n; ++i)
- if (arr[i].value > r.pair.value)
- arr[i].direction = !arr[i].direction;
- }
- public:
- CArrangement(size_t k) : n(k)
- {
- size_t i;
- arr = new CIntPair<T>[n];
- for (i = 0; i < n; ++i)
- {
- arr[i].direction = CIntPair<T>::LEFT;
- arr[i].value = i + 1;
- }
- }
- CArrangement(const T & initial, size_t k) : n(k)
- {
- size_t i;
- arr = new CIntPair<T>[n];
- for (i = 0; i < n; ++i)
- {
- arr[i].direction = CIntPair<T>::LEFT;
- arr[i].value = static_cast<T>(i + initial);
- }
- }
- ~CArrangement()
- {
- delete[] arr;
- n = 0;
- }
- bool Permute()
- {
- if (n <= 1)
- return false;
- // 1st. find the maximun movable number in arr list as r.
- CRtn r = MaxMovableIndex();
- if (r.found)
- {
- // 2nd. Swap r with the number adjacent to r.
- Swap(r.index);
- // 3rd. Change all directions of p, such that p > r.pair.value.
- ChangeDirection(r);
- ++counter;
- }
- return r.found;
- }
- template <class TX>
- friend ostream & operator << (ostream & o, const CArrangement<TX> & ra);
- };
- template <class T>
- ostream & operator << (ostream & o, const CArrangement<T> & ra)
- {
- size_t i;
- o << ra.counter << ":\t";
- for (i = 0; i < ra.n; ++i)
- o << ra.arr[i].value << " ";
- return o;
- }
- int main(void)
- {
- CArrangement<int> a(4);
- cout << a << endl;
- while (a.Permute())
- cout << a << endl;
- return 0;
- }
复制代码
以上代码执行结果如下:
1: 1 2 3 4
2: 1 2 4 3
3: 1 4 2 3
4: 4 1 2 3
5: 4 1 3 2
6: 1 4 3 2
7: 1 3 4 2
8: 1 3 2 4
9: 3 1 2 4
10: 3 1 4 2
11: 3 4 1 2
12: 4 3 1 2
13: 4 3 2 1
14: 3 4 2 1
15: 3 2 4 1
16: 3 2 1 4
17: 2 3 1 4
18: 2 3 4 1
19: 2 4 3 1
20: 4 2 3 1
21: 4 2 1 3
22: 2 4 1 3
23: 2 1 4 3
24: 2 1 3 4
本算法来自:Richard A. Brualdi Introductory Combinatorics, Fifth Edition
以上源代码已经经过了修改。引入模板类,目的是为了能像STL的函数一样对任意整数类型进行排列。
这样就能排列char类型的数据:
- int main(void)
- {
- CArrangement<char> a('A', 3);
- cout << a << endl;
- while (a.Permute())
- cout << a << endl;
- return 0;
- }
复制代码
结果如下:
1: A B C
2: A C B
3: C A B
4: C B A
5: B C A
6: B A C
|
|