栈  0.1
数据结构_第3章
Permute.hh
Go to the documentation of this file.
1 
12 #ifndef __PERMUTE_HH__
13 #define __PERMUTE_HH__
14 
15 #include "Stack.hh"
16 #include <algorithm>
17 #include <ctime>
18 #include <iostream>
19 #include <string>
20 #include <utility>
21 
22 namespace ch3_3
23 {
24 // 工具: 交换
25 // 参考: http://www.cplusplus.com/reference/algorithm/swap/
26 template <class T>
27 void swap(T &a, T &b)
28 {
29  T c(std::move(a));
30  a = std::move(b);
31  b = std::move(c);
32 }
33 
34 // 工具: 逆序[first, last)
35 // 参考: https://en.cppreference.com/w/cpp/algorithm/reverse
36 template <class BidirIt>
37 void reverse(BidirIt first, BidirIt last)
38 {
39  while ((first != last) && (first != --last))
40  swap(*first++, *last);
41 }
42 
43 // 工具: 递归输出固定前缀[first, fixPos)的[first, last)的全排列. fixPos为first表示不固定任何元素.
44 // 参考: https://leetcode-cn.com/problems/permutations-ii/
45 template <class BidirIt>
46 void permuteWithFixedPrefix(BidirIt first, BidirIt last, BidirIt fixPos)
47 {
48  /* BEGIN: stage-0 */
49  if (fixPos == last)
50  {
51  for (BidirIt i = first; i != last; ++i)
52  std::cout << *i;
53  std::cout << std::endl;
54  return; // GOTO: return
55  }
56  /* END: stage-0 */ // PUSH: stage-1
57 
58  // 任务: 输出固定前缀[first, fixPos)的全排列. 可分解为:
59  // 令[fixPos, last)间各数依次占据fixPos位, 然后输出固定前缀[first, fixPos]的全排列.
60  for (BidirIt i1 = fixPos; i1 != last; ++i1)
61  {
62  /* BEGIN: stage-1 */
63  // 判断是否重复分支:
64  // 若i1所指已在[fixPos, i1)中出现, 则此分支为重复
65  bool isRep = false;
66  for (BidirIt i2 = fixPos; i2 < i1; ++i2)
67  {
68  if (*i1 == *i2)
69  {
70  isRep = true;
71  break;
72  }
73  }
74  if (isRep) // 跳过重复分支 // PUSH: stage-1, then return
75  continue;
76 
77  swap(*i1, *fixPos);
78 
79  BidirIt i = fixPos;
80  /* END: stage-1 */ // PUSH stage-2
81  permuteWithFixedPrefix(first, last, ++i);
82 
83  /* BEGIN: stage-2 */
84  swap(*i1, *fixPos);
85  // ++i1;
86  /* END: stage-2 */ // PUSH: stage-1
87  }
88 }
89 
90 // 工具: 栈模拟的递归输出固定前缀[first, fixPos)的[first, last)的全排列. fixPos为first表示不固定任何元素.
91 // 参考: https://www.codeproject.com/Articles/418776/How-to-replace-recursive-functions-using-stack-and
92 template <class BidirIt>
93 void permuteWithFixedPrefix_Loop(BidirIt first, BidirIt last, BidirIt fixPos)
94 {
95  struct SnapShotStruct
96  {
97  BidirIt first; // - parameter input
98  BidirIt last;
99  BidirIt fixPos;
100  BidirIt i1; // for-loop
101  int stage;
102  };
103 
104  Stack::linkStack<SnapShotStruct> snapshotStack;
105  SnapShotStruct currentSnapshot;
106  currentSnapshot.first = first;
107  currentSnapshot.fixPos = fixPos;
108  currentSnapshot.last = last;
109  currentSnapshot.i1 = fixPos;
110  currentSnapshot.stage = 0;
111  snapshotStack.push(currentSnapshot);
112 
113  while (!snapshotStack.isEmpty())
114  {
115  currentSnapshot = snapshotStack.top();
116  snapshotStack.pop();
117 
118  switch (currentSnapshot.stage)
119  {
120  case 0:
121  {
122  if (currentSnapshot.fixPos == currentSnapshot.last)
123  {
124  for (BidirIt i = currentSnapshot.first; i != currentSnapshot.last; ++i)
125  std::cout << *i;
126  std::cout << std::endl;
127 
128  continue;
129  }
130 
131  currentSnapshot.stage = 1;
132  snapshotStack.push(currentSnapshot);
133  continue;
134  break;
135  }
136  case 1:
137  {
138  if (currentSnapshot.i1 == currentSnapshot.last)
139  continue;
140 
141  bool isRep = false;
142  for (BidirIt i2 = currentSnapshot.fixPos; i2 < currentSnapshot.i1; ++i2)
143  {
144  if (*currentSnapshot.i1 == *i2)
145  {
146  isRep = true;
147  break;
148  }
149  }
150  if (isRep) // 跳过重复分支
151  {
152  ++currentSnapshot.i1;
153  currentSnapshot.stage = 1;
154  snapshotStack.push(currentSnapshot);
155  continue;
156  }
157 
158  swap(*currentSnapshot.i1, *currentSnapshot.fixPos);
159 
160  currentSnapshot.stage = 2;
161  snapshotStack.push(currentSnapshot);
162 
163  // new call
164  currentSnapshot.i1 = ++currentSnapshot.fixPos;
165  currentSnapshot.stage = 0;
166  snapshotStack.push(currentSnapshot);
167  continue;
168  break;
169  }
170  case 2:
171  {
172  swap(*currentSnapshot.i1, *currentSnapshot.fixPos);
173 
174  ++currentSnapshot.i1;
175  currentSnapshot.stage = 1;
176  snapshotStack.push(currentSnapshot);
177  continue;
178  break;
179  }
180  }
181  }
182 }
183 
184 // 递归输出_s的全排列
185 template <class T>
186 void permute_rec(const T &_s)
187 {
188  if (_s.empty())
189  throw(std::string{"Empty container!\n"});
190  T s = _s;
191 
192  permuteWithFixedPrefix(s.begin(), s.end(), s.begin());
193 }
194 
195 // 栈模拟的递归输出_s的全排列
196 template <class T>
197 void permute_loop(const T &_s)
198 {
199  if (_s.empty())
200  throw(std::string{"Empty container!\n"});
201  T s = _s;
202 
203  permuteWithFixedPrefix_Loop(s.begin(), s.end(), s.begin());
204 }
205 
206 // 工具: 非递归地使序列变为下一排序[first, last)
207 // 参考: https://en.cppreference.com/w/cpp/algorithm/next_permutation
208 template <class BidirIt>
209 bool next_perm(BidirIt first, BidirIt last)
210 {
211  if (first == last) // 若序列为空, 结束.
212  return false;
213  BidirIt i = last;
214  if (first == --i) // 令i指向最后一个元素. 若序列仅含一个元素, 结束.
215  return false;
216 
217  while (true)
218  {
219  BidirIt i1, i2;
220 
221  i1 = i;
222  if (*--i < *i1) // 若已从低位向高位找到了首个逆序(高位小于低位). 此时i和i1指向这对逆序
223  {
224  i2 = last;
225  while (!(*i < *--i2)) // 令i2指向从低位向高位首个大于*i的数
226  ;
227  swap(*i, *i2);
228  ch3_3::reverse(i1, last);
229  return true;
230  }
231  if (i == first) // 若序列已是顺序的(从高位向低位为非增), 则不存在更大的排序, 结束.
232  {
233  ch3_3::reverse(first, last); // 当前排序是最大排序, 逆置后成为最小排序
234  return false;
235  }
236  }
237 }
238 
239 // 非递归输出_s的全排列
240 template <class T>
241 void permute_stl(const T &_s)
242 {
243  T s = _s;
244  std::sort(s.begin(), s.end());
245 
246  do
247  {
248  std::cout << s << '\n';
249  } while (next_perm(s.begin(), s.end()));
250 }
251 
252 } // namespace ch3_3
253 
254 #endif
ch3_3::reverse
void reverse(BidirIt first, BidirIt last)
Definition: Permute.hh:37
Stack::linkStack::push
virtual void push(const T &elem)
Definition: linkStack.hpp:76
ch3_3::permute_loop
void permute_loop(const T &_s)
Definition: Permute.hh:197
ch3_3
Definition: Permute.hh:22
Stack::linkStack
Definition: linkStack.hpp:21
Stack::linkStack::top
virtual T top() const
Definition: linkStack.hpp:100
ch3_3::permuteWithFixedPrefix
void permuteWithFixedPrefix(BidirIt first, BidirIt last, BidirIt fixPos)
Definition: Permute.hh:46
ch3_3::permuteWithFixedPrefix_Loop
void permuteWithFixedPrefix_Loop(BidirIt first, BidirIt last, BidirIt fixPos)
Definition: Permute.hh:93
Stack::linkStack::pop
virtual T pop()
Definition: linkStack.hpp:88
ch3_3::swap
void swap(T &a, T &b)
Definition: Permute.hh:27
Stack.hh
栈的抽象类
Stack::linkStack::isEmpty
virtual bool isEmpty() const
Definition: linkStack.hpp:106
ch3_3::permute_rec
void permute_rec(const T &_s)
Definition: Permute.hh:186
ch3_3::permute_stl
void permute_stl(const T &_s)
Definition: Permute.hh:241
ch3_3::next_perm
bool next_perm(BidirIt first, BidirIt last)
Definition: Permute.hh:209