[关闭]
@smilence 2013-10-29T08:11:36.000000Z 字数 3248 阅读 3681

Chapter 3 Stacks and Queues


“The Rules"

1.C++ STL中<stack><queue>的常用函数:
<stack>: empty(),pop(), top(),push(const val_type &);
<queue>:empty(),pop(),front(),push(const val_type &);

2.stackqueue 可以视作封装好的Linked list,限制了访问和插入的自由。因此适用stackqueue的情境,也可以考虑使用更为强大的list

3.stack与Recursion的关系:recursion在底层用stack实现。入栈操作等价于递归调用,出栈操作等价于递归返回。出入栈操作的对象,即为当前等待先后解决的的subproblem。


模式识别


1.用stack实现依赖顺序读取的功能
stack具有LIFO的特性,如需实现任何依赖顺序或随机读取的常规操作,往往可以借助两个stack"同向"或"反向"来实现。( 反向时,往往需要互相"倾倒"来实现特定顺序。)

e.g. 1 Design a stack with push(), pop() and min() in O(1) time. ( CtCI 3.2 )
e.g. 2 Implement a queue with two stacks.( CtCI 3.5 )
e.g. 3 Sort a stack in ascending order with an additional stack.( CtCI 3.6)

2."Save for later"问题
关于"收敛结构"与"发散结构"的解释,详见"Chapter 7 Recursion and Dynamic Programming"。

处理收敛结构问题,如果无论从哪一端出发,都避免不了"(部分)当前节点的解依赖后驱节点"(也就是说,当前节点,如果不能获知后驱节点,就无法得到有意义的解),那么可以用backtracking(如果前进方向已知),或stack(或等同于stack的若干个临时变量)解决。当前节点入栈,直到依赖的所有节点都完备时再取出求解,必要时将结果再次入栈。

e.g.1 Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid. ( Leetcode: Valid Parentheses )
e.g.2 Evaluate a Postfix Notation (Reverse Polish Notation)

  1. //Reverse Polish Notation (RPN)
  2. double rpn(stringstream &input){
  3. string tok;
  4. double val;
  5. stack<double> res;
  6. while(input>>tok){
  7. if( isdigit(tok[0] ){
  8. streamstream tmp(tok);
  9. tmp >> val;
  10. res.push(val);
  11. }
  12. switch(tok[0]){
  13. case '*':
  14. val = res.top();
  15. res.pop();
  16. val = res.top() * val ;
  17. res.pop();
  18. res.push( val );
  19. break;
  20. ...
  21. }
  22. }
  23. return res.top();
  24. }

e.g.3 Evaluate a Prefix Notation (Polish Notation)

  1. double pn(stringstream& input) {
  2. string tok;
  3. input >> tok;
  4. double res;
  5. switch (tok[0]) {
  6. case '+': return pn(input) + pn(input);
  7. case '-': return pn(input) - pn(input);
  8. case '/': return pn(input) / pn(input);
  9. case '*': return pn(input) * pn(input);
  10. }
  11. stringstream tmp(tok);
  12. if( isdigit(tok[0]) )
  13. tmp >> res;
  14. return res;
  15. }

stack求解的办法,参见 http://stackoverflow.com/questions/3205723/how-to-evaluate-an-expression-in-prefix-notation/13781413#13781413

3.用stack解决Top-Down的发散结构问题

用Recursion解决Top-Down的发散结构问题,详见Chapter 7。

在使用D&C策略时,如果每个subproblem,处理的是单个同样类型的object,则可以将该object按照Top-down的方向入栈,然后循环pop()来访问。如果subproblem的size不同,则可将他们声明为同种类型的object,按照Top-Down的方向入栈;最后pop()访问时,再将复合的subproblem拆解,push入栈;如此循环直至stack清空。(类似queue结构在BFS中的作用)

e.g.1 Binary Search Tree In-Order Traversal Iterative

  1. void inorderTraversal(TreeNode *root) {
  2. if(root == NULL)
  3. return;
  4. stack<TreeNode *> st;
  5. while(!st.empty() || root ){
  6. /* The 3 Nodes: root, left and right can actually be regarded as 3 subtrees( same type ), though we did little optimization here so we only push 1 subtree instead of 3 at one time( always the root ).*/
  7. if(root){
  8. st.push(root);
  9. root = root->left;
  10. }else{
  11. root = st.top();
  12. st.pop();
  13. visit( root );
  14. root = root->right;
  15. }
  16. }
  17. }

e.g.2 Solve the Hanoi Tower problem without recursion

  1. enum Tower { Zero,Left, Mid, Right};
  2. class HanoiObj{
  3. public:
  4. Tower src,tmp,dest;
  5. int num,index;
  6. HanoiObj(Tower s,Tower t,Tower d,int n):src(s),tmp(t),dest(d),num(n){
  7. if(n == 1) index = 1;
  8. }
  9. HanoiObj(Tower s,Tower d,int i):src(s),dest(d),index(i){
  10. num = 1; tmp = Zero;
  11. }
  12. };
  13. void move( Tower src, Tower dest,int index){
  14. cout << "Move Disk #" << index <<" from Tower " << src << " to Tower " << dest << endl;
  15. }
  16. void TOH(int N, stack<HanoiObj*>&Hstack){
  17. Tower s,t,d;
  18. int n;
  19. Hstack.push(new HanoiObj(Left,Mid,Right,N));
  20. while( !Hstack.empty()){
  21. HanoiObj *tmpObj = Hstack.top();
  22. Hstack.pop();
  23. s = tmpObj->src;
  24. t = tmpObj->tmp;
  25. d = tmpObj->dest;
  26. n = tmpObj->num;
  27. if(n < 1) continue;
  28. if(n == 1)
  29. move(s,d,tmpObj->index);
  30. else{
  31. Hstack.push(new HanoiObj(t,s,d,n-1));
  32. Hstack.push(new HanoiObj(s,d,n));
  33. Hstack.push(new HanoiObj(s,d,t,n-1));
  34. }
  35. delete tmpObj;//
  36. }
  37. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注