简体   繁体   English

使用二叉树的级别顺序递归查找节点 - C

[英]finding a node using level-order recursion of a Binary Tree - C

In C, I need to recursively search through a Binary Tree (max heap) to find if a node is in the heap, and then return a pointer to that node, or NULL if not found.在 C 中,我需要递归搜索二叉树(最大堆)以查找节点是否在堆中,然后返回指向该节点的指针,如果未找到则返回 NULL。 My recursive function always seems to recurs through the whole tree even after I find the value and try to return the node.即使在我找到值并尝试返回节点之后,我的递归 function 似乎总是在整个树中递归。 I can never seem to quite wrap my head around recursion and have been stuck on this for a while.我似乎永远无法完全理解递归,并且已经坚持了一段时间。 Here is my original code / pseudo code if anyone can point out if I'm logically thinking about this wrong.这是我的原始代码/伪代码,如果有人能指出我是否在逻辑上思考这个错误。

Node* find_node(Heap *max_heap, int *key) {

Node *node = NULL;

node = find_node_aux(root, key);

return node;`
}`



 Node* find_node_aux(Node, key) {


if (node == NULL)
    return NULL;
if (Node == Key) {
    return node;
}

if (node->left != NULL)
    find_node_aux(node->left, d);
    
if (node->right != NULL)
    find_node_aux(node->right, d);


return NULL;
}

I think my issue with recursion is that i treat it like a loop when its not really.我认为我对递归的问题是当它不是真的时我把它当作一个循环。 And I also realized i wasn't returning anything on the recursion, so i switched up my code to this而且我还意识到我没有在递归中返回任何东西,所以我将我的代码切换到这个

if (node == NULL)
        return NULL;
     
    if (node != key) {
        if (node->left != NULL)
            node = find_node_aux(node->left, d);
        if (node->right != NULL)
            node = find_node_aux(node->right, d);

}

return node;
}

but it always stops and returns the same node in the tree for some reason.但由于某种原因,它总是停止并返回树中的相同节点。 I know this question is probably simple but i really struggle with recursion.我知道这个问题可能很简单,但我真的很难递归。 (i know the indenting probably looks weird its just the way i entered into this question, im more confused about the logic) (我知道缩进可能看起来很奇怪,就像我进入这个问题的方式一样,我对逻辑更加困惑)

  • If the node you are seeking isn't in the left half, you are clobbering node before checking the right half.如果您正在寻找的节点不在左半边,那么您在检查右半边之前正在破坏node
  • If the node you are seeking is in left half, you are proceed to try to search the right half of the tree too, clobbering node in the process.如果您正在寻找的节点在左半边,您将继续尝试搜索树的右半边,在此过程中破坏node

Fixed:固定的:

if (node == NULL)
   return NULL;

if (node.value == value)
   return node;

if (node->left) {
   Node *found = find_node(node->left, value);
   if (found)
      return found;
}

if (node->right) {
   Node *found = find_node(node->right, value);
   if (found)
      return found;
}

return NULL;

The following is another approach:以下是另一种方法:

  1. If the tree is empty,如果树是空的,
    1. Return NULL.返回 NULL。
  2. Create a to-visit stack.创建一个访问堆栈。
  3. Push the root node onto the stack.将根节点压入堆栈。
  4. While the stack isn't empty,虽然堆栈不是空的,
    1. Pop a node from the stack.从堆栈中弹出一个节点。
    2. If the node is the one being sought,如果节点是正在寻找的节点,
      1. Free the stack.释放堆栈。
      2. Return the node.返回节点。
    3. If the node has a left child,如果节点有左孩子,
      1. Push the left child onto the stack.将左孩子推入堆栈。
    4. If the node has a right child,如果节点有右孩子,
      1. Push the right child onto the stack.将右孩子推入堆栈。
  5. Free the stack.释放堆栈。
  6. Return NULL.返回 NULL。

They're really two versions of the same approach.它们实际上是同一方法的两个版本。 The former simply uses the call stack as the to-visit stack.前者只是将调用堆栈用作访问堆栈。

There's a problem.有问题。 Both of the above perform a depth-first search, but you said you wanted to use a breadth-first search (level-order traversal).以上两个都执行深度优先搜索,但您说您想使用广度优先搜索(级别顺序遍历)。 A very small change is needed to the algorithm presented above to achieve this: Use a queue instead of stack.要实现这一点,需要对上面介绍的算法进行非常小的更改:使用队列而不是堆栈。

  1. If the tree is empty,如果树是空的,
    1. Return NULL.返回 NULL。
  2. Create a to-visit queue.创建访问队列。
  3. Enqueue the root node onto the queue.将根节点排入队列。
  4. While the queue isn't empty,虽然队列不是空的,
    1. Dequeue a node from the queue.从队列中取出一个节点。
    2. If the node is the one being sought,如果节点是正在寻找的节点,
      1. Free the queue.释放队列。
      2. Return the node.返回节点。
    3. If the node has a left child,如果节点有左孩子,
      1. Enqueue the left child onto the queue.将左孩子排入队列。
    4. If the node has a right child,如果节点有右孩子,
      1. Enqueue the right child onto the queue.将正确的孩子排入队列。
  5. Free the queue.释放队列。
  6. Return NULL.返回 NULL。

Since recursion provides a stack, recursion isn't useful here.由于递归提供了堆栈,因此递归在这里没有用处。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM