树递归查找遇到的问题。

本以为树查找和遍历算法一摸一样,无非就是找到元素后return节点地址。但是写代码的时候还是发现有区别。
先看这个代码,这是一棵树,每一个节点有多个子节点(数目不定,不是二叉树)。树的结构如下:

class Node
{
public:
    Node(int d = 0) : data(d)
    {
        children.clear();
    }
    int data;
    vector<Node *> children;
};

为了简化操作,用了vector,反正这是一个无序的树,用vector比自己再写一个链表方便多了.
最初树的查找算法如下:

Node *find(Node *parent, int d)
{
    static bool yesfind = false;
    if (parent == nullptr)
        return nullptr;
    if (parent->data == d)
    {
        yesfind = true;
        return parent;
    }
    else
    {
        for (auto it = parent->children.begin(); it != parent->children.end(); it++)
        {
            if (yesfind == false)
            {
               find(*it, d);
            }
        }
    }
}

代码显然用了递归,变量yesfind的作用是为了在已经找到元素的情况下,避免接着执行for循环,猛一看代码没问题,但是实际执行发现,每次返回的都是根节点,单步debug发现,在递归返回的时候,因为parent每次压栈的值不一样,所以出栈的值也会不变,最后出栈的是根节点,所以每次即便找到节点,return的也不是这个节点的地址,最终都会变成root的地址,所以我们需要报讯这个return的节点地址,因此代码修改如下:

Node *find(Node *parent, int d)
{
    static bool yesfind = false;
    if (parent == nullptr)
        return nullptr;
    if (parent->data == d)
    {
        yesfind = true;
        return parent;
    }
    else
    {
        for (auto it = parent->children.begin(); it != parent->children.end(); it++)
        {
            if (yesfind == false)
            {
                Node *t = find(*it, d);
                if (t)
                    return t;
            }
        }
    }
    if (yesfind == false)
        return nullptr;
}

可以看出,我们修改了两部分:
1.修改for循环,可以保存节点地址
2.结尾添加判断yesfind,防止在没有找到节点的情况下,由于最后根节点出栈而返回根节点的地址.

posted @ 2021-04-02 20:54  大神的老爸  阅读(93)  评论(0编辑  收藏  举报