在二叉搜索树的节点中存储某些叶子的数量(优化)

时间:2017-11-03 16:28:48

标签: c++ binary-search-tree

我必须为每个子树计算带有偶数标签的叶子的数量,其父亲具有奇数标签,带有奇数标签的叶子的数量,其父亲甚至具有标签并将该数字存储在子树的节点中。

例如:this tree(输出在左侧)。

这是我的代码

struct node {
    int label;
    node*right;
    node*left;
    int L; //i use this to store the number of leaves
};

void addnodeBST(node*&tree, int l) { //adds a node
    if (!tree) {
        tree = new node;
        tree->label = l;
        tree->right = tree->left = 0;
        tree->L = 0;
        return;
    }
    if (l < tree->label)
        addnodeBST(tree->left, l);
    if (l > tree->label)
        addnodeBST(tree->right, l);
}

int counter(node*tree, int x) { 
    if (!tree)
        return 0;
    if ((!tree->left && !tree->right) && ((x % 2 == 0 && tree->label % 2 == 
       1) || (x % 2 == 1 && tree->label % 2 == 0)))
        return 1;
    return counter(tree->left, tree->label) + counter(tree->right, tree-
    >label);
}

void updateNode(node*tree) {
    if (!tree)
        return;
    tree->L = counter(tree, 0);
    if (!tree->right && !tree->left)
        tree->L = 0;
    updateNode(tree->left);
    updateNode(tree->right);
}

它有效,不一样的是“counter”和“updateNode”功能。

“计数器”计算要计算的叶数。

“UpdateNode”使用“counter”来计算,然后将每个子树中的叶子数存储到L中(我在结构中定义)。

这样我有一个递归函数到另一个递归函数,我多次访问每个节点。

如何优化代码?

1 个答案:

答案 0 :(得分:0)

  

这样我有一个递归函数到另一个递归函数,我多次访问每个节点。

and之前的部分使你的代码变得丑陋,但真正的魔鬼在于你如何选择遍历树。

updateNode函数中,节点的L值只是它左右子树的总和。因此,如果您之前调用它们(后序),而不是像现在这样在函数结束时调用它们(预订);现在你知道了他们的L,而不是打电话给counter,你只需将它们添加起来即可。您只需访问每个节点一次。

您可以完全删除counter功能。

这是修改后的代码(注释解释代码):

//helper to check leaves, null nodes are not leaf
bool isLeaf(node* tree){
    return (tree && (!tree->right) && (!tree->left));
}

//change return type to catch child node's 'L' value through recursive calls 

int updateNode(node*tree) { 
    if (!tree) return 0; //0 for null, for example tree->right for '24'
    if (isLeaf(tree)) tree->L = 0; //All the leaves

    int a,b;
    //find 'L' for left child into a
    if(isLeaf(tree->left)){
        if(tree->left->label%2!=tree->label%2) a=1; //this will be true for '24' and '10'
        else a=0;
    }  
    else a = updateNode(tree->left);

    //Now find 'L' for right child into b
    if(isLeaf(tree->right)){ //this will be true for '10'
        if(tree->right->label%2!=tree->label%2) b=1;
        else b=0;
    }
    else b = updateNode(tree->right);

    //combine them
    tree->L = a+b; //this will be true for '20'
    return tree->L; //return for parent's sake
}

驱动程序运行它:

void inorder(node* tree){
    if(!tree) return ;
    inorder(tree->left);
    printf("%d : %d %d\n",tree->label,tree->L,isLeaf(tree) ); 
    inorder(tree->right);
}

int main(int argc, char const *argv[])
{
    node* tree = 0;
    addnodeBST(tree,20);
    addnodeBST(tree,10);
    addnodeBST(tree,24);
    addnodeBST(tree,17);
    addnodeBST(tree,23);
    addnodeBST(tree,5);
    updateNode(tree);
    inorder(tree);
    return 0;
}

并且......你的addnodeBST将因同等价值而失败。将第二个if更改为else