在C中搜索递归数据结构

时间:2016-09-11 07:55:10

标签: c recursion tree

我想帮助编写一个递归搜索函数。

我有一个如下所示的数据结构:

struct node_t {
    char       name[16];    
    int        num_children;
    node_t**   children;
};

我有很多节点在一个深树状结构中,每个节点可以有很多孩子。

要在树中的某处找到节点,我目前将根节点传递给此函数:

node_search(node_t* parent, const char* node_name) {

    if(strcmp(parent->name, node_name) == 0) {
        return parent;
    } 
    else {
        for(int i = 0; i < parent->num_children; ++i) {
            node_t* node_found = node_search(parent->children[i], node_name);

            if(strcmp(node_found->name, node_name) == 0) {
                return node_found;
            }           
        }
    }
}

这似乎有效,但我观察到的两件事让我担心这不是最佳/正确的方法:

  1. 当在树中找到所需的节点时,在递归的路上,调用堆栈中的每个帧都会完成strcmp

  2. 当遍历树中没有所需节点的分支时,循环内的strcmp最终会对垃圾值进行比较,这样就不会感觉非常稳固。 / p>

  3. 有人知道这种递归搜索可以用更好的方式完成吗?

2 个答案:

答案 0 :(得分:2)

您需要在所有路径上都有一个返回值,并解决编译器应该给您的警告,这将使您理解NULL是找不到任何内容时唯一合理的选择。

通过这种方式,您可以通过在修复此问题时消除冗余检查来显着减少代码。你这里不需要两个strcmp。你在子弹列表中提到:“......循环中的strcmp ......” - 你已经在循环中一个strcmp;它是在对该孩子的递归调用中完成的。再做一次是没有意义的。

node_t* node_search(node_t* parent, const char* node_name)
{
    if(strcmp(parent->name, node_name) == 0)
        return parent;

    node_t *node_found = NULL;
    for(int i = 0; !node_found && i < parent->num_children; ++i)
        node_found = node_search(parent->children[i], node_name);

    return node_found;
}

如果找不到该元素,那么应该返回NULL,并且在找到 节点后立即断开循环,返回链。

最后,根据此代码的位置,可能希望确保parent在打开解除引用之前不为NULL。此代码假定在没有parent的有效非空指针的情况下永远不会调用它。这是否是一个有效的假设(显然是在你发布的代码中)我留给你决定。

答案 1 :(得分:1)

你的函数应该在循环之外返回NULL

在循环内部,您应该检查返回的值是否不是NULL,如果不是,那么内部框架已经为您进行了比较,所以只需打破循环并返回相同的值。

所以:

if (node_found != NULL)
  return node_found;