以递归方式检索二叉树节点的深度

时间:2009-06-17 13:01:32

标签: recursion binary-tree non-recursive

有人能指出在不使用递归的情况下在二叉树(不是平衡的,或BST)中获取节点深度的方法吗?理想情况下在Java / C / C#

节点表示为:

class Node
{
  Node Left;
  Node Right;
  string Value;
  int Depth;
}

使用级别顺序和FIFO列表是我的第一个想法,但是我很难过检测水平何时发生变化,特别是对于不平衡的树木。

4 个答案:

答案 0 :(得分:6)

你可以使用堆栈实现任何resursive方法,这是resursion无论如何都可以工作的方式。想象一下你的resursive函数看起来像

function int getDepth (Node head, string val)
{
    if (head == NULL)
        return -1;

    if (val == head.Value)
        return head.Depth;

    return MAX(getDepth(head.Left, val), getDepth(head.Right, val);
}

非反复功能看起来像

function int getDepth (Node head, string val)
{
    Stack s = new Stack();

    s.push(head);

    while(s.count > 0)
    {
        Node temp = s.pop();

        if (temp != NULL)
        {
            if (s.Value == val)
                return s.Depth;
            else
            {
                s.push(temp.Left);
                s.push(temp.Right);
            }
        }

    }


    return -1;
}

编辑:

此函数设置每个节点的深度

function void setDepth (Node head)
{
    Stack s = new Stack();

    head.Depth = 0;
    s.push(head);

    while(s.count > 0)
    {
        Node temp = s.pop();

        if (temp != NULL)
        {
            if (temp.Left != NULL)
            {
                temp.Left.Depth = temp.Depth + 1;
                s.push(temp.Left);
            }

            if (temp.Right != NULL)
            {
                temp.Right.Depth = temp.Depth + 1;
                s.push(temp.Right);
            }
        }

    }

}

答案 1 :(得分:6)

我假设您的意思是填充节点上的深度值,和/或找到最大深度。一种方法是使用两个列表,并按照建议执行级别顺序。它类似于:

int level=0;
List<Node> currentLevel = new List<Node>{root};
while(currentLevel.Count != 0)
{
  List<Node> nextLevel = new List<Node>{};
  foreach(Node node in currentLevel)
  {
    if(node.Right!=null) nextLevel.Add(node.Right);
    if(node.Left != null) nextLevel.Add(node.Left);
    node.Depth=level;
  }
  level++;
  currentLevel=nextLevel;
}

基本上,您枚举给定级别的每个节点,然后在下一级找到每个节点;直到你用完节点/级别。显然,List可以替换为任何列表,如数据结构(链接列表,队列等)。而“水平”的最后一个值将是最大深度+1。我怀疑。

基于重新阅读问题的另一个澄清;如果要搜索具有特定值的节点,并且想要查找其深度,则可以将foreach循环更改为包含“if(node.Value == searchValue)返回级别”。而且,从技术上讲,如果要搜索特定值,则不应该进行级别顺序遍历,而应使用相关二进制树属性搜索值(例如val&lt; currentNode.Value goto left else goto right) ,并跟踪你的深度。如果您只获得节点并想要查找其深度,则需要从根目录执行节点的二进制搜索,或者您需要跟踪节点的父节点。

答案 2 :(得分:2)

我认为这是一个更简单的解决方案。如果数据结构允许任意数量的子节点,那么也可以很容易地修改此解决方案:

int getDepthNoRecursion(Node n) {
  if(n == null) {
    return 0;
  }
  int retval = 0;
  n.depth = 1;
  Stack s = new Stack();
  s.push(n);
  while(!s.isEmpty()) {
    Node n = (Node) s.pop();
    int currDepth = n.depth;
    if(currDepth > retval) {
      retval = currDepth;
    }
    if(n.left != null) {
      n.left.depth = currDepth + 1;
      s.push(n.left);
    }
    if(n.right != null) {
      n.right.depth = currDepth + 1;
      s.push(n.right);
    }
  }
  return retval;
}
class Node {
  Node left;
  Node right;
  int depth = 0;
}

答案 3 :(得分:0)

这是我提出的最有效的解决方案(C ++)。诀窍是使用第二个队列来存储当前级别的所有节点的子节点。这适用于平衡和不平衡的二叉树。

template <class T>
struct TreeNode {
  TreeNode<T>* left_;
  TreeNode<T>* right_;
  T* data_;
};

template <class T>
int find_depth( const TreeNode<T>* root ) {   
  if ( root == NULL ) return 0;
  int depth = 0;
  std::queue<const TreeNode<T>*>* q1 = new std::queue<const TreeNode<T>*>;
  std::queue<const TreeNode<T>*>* q2 = new std::queue<const TreeNode<T>*>;
  q1->push( root );
  while ( !q1->empty() ) {
    // At the top of the outer loop q1 contains a complete horizontal level of the tree                                                                                  
    depth++;

    // Swap the queue pointers to avoid any deep copies                                                                                                                  
    std::queue<const TreeNode<T>*>* tmpQ = q2;
    q2 = q1;
    q1 = tmpQ;

    // Iterate over this level, inserting all children into q1                                                                                                           
    while( !q2->empty() ) {
      const TreeNode<T>* node = q2->front();
      if ( node->left_ != NULL ) q1->push( node->left_ );
      if ( node->right_ != NULL ) q1->push( node->right_ );
      q2->pop();
    }
  }
  delete q1;
  delete q2;
  return depth;
}