最近写代码的一些感悟

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

 

posted @ 2020-05-06 22:24  FizzPu  阅读(190)  评论(0编辑  收藏  举报