最近写代码的一些感悟
1.数组问题
在设计循环双端队列时,数组最大尺寸为max。队尾指针每一次后移,改rear = (rear + 1) % max;
队头指针每一次前移动,改front = (front - 1 + max) % max;
2.利用标志位简化if else
今天在用递归改写树的后序遍历时,
具体思路:
我的代码
enum Tag{R,L};//L:右子树还未访问过,R:右子树已近访问过 // 利用前序遍历的方法创建二叉链表 // 有点类似dfs算法 struct Subtree { char data; Subtree* right; Subtree* left; Tag tag; Subtree(int m_data):right(nullptr),left(nullptr), data(m_data),tag(L){} }; void last(Subtree * root){ if(root == nullptr)return; stack<Subtree *> mystack; Subtree * p = root; do {
//找到左下角那个节点 while(p != nullptr){ mystack.push(p); p = p -> left; } if (!mystack.empty()){ p = mystack.top(); if(p -> tag == L){//右子树还没访问过,进右子树 p -> tag = R; p = p -> right;} else {//右子树已近访问过,直接访问 while(!mystack.empty() && p -> tag == R){ cout<<p -> data; mystack.pop(); if(mystack.empty()){break;} p = mystack.top(); } //进右子树
p -> tag = R; p = p-> right; } } } while(!mystack.empty()); }
这逻辑也是迷人啊,而且if else 到处飞,看看别人的代码,使用一个标志位来处理两种情况。
void last_far(Subtree * root){ if(root == nullptr)return; stack<Subtree *> mystack; Subtree * p = root; do { while(p != nullptr){ mystack.push(p); p = p -> left; } int flag = 0; while(!mystack.empty() && flag == 0){ p = mystack.top(); switch (p -> tag) { case L: p -> tag = R; p = p -> right; flag = 1;//循环一次 break; case R: cout << p -> data; mystack.pop(); break; } } } while(!mystack.empty()); }
3.函数内部修改函数的参数时,一定要小心。像上面的例子中,函数执行一次,这棵树的tag全被改为了R。下一次调用这个函数将会出现难以发现的bug。
我的处理思路:1.遍历结束后,再遍历一次,把tag改为L 。2.栈里面存树的节点,每一次入栈,就把这个节点复制一份再入栈。
所以,我觉得按值传递虽然效率低,但是他安全啊。以后,按指针传递最好把函数参数声明为const