谁能指出一种在不使用递归的情况下获取二叉树(不是平衡树或 BST)中节点深度的方法?理想情况下使用 Java/C/C#
节点表示为:
class Node
{
Node Left;
Node Right;
string Value;
int Depth;
}
我的第一个想法是使用带有 FIFO 列表的 Level Order,但我在检测级别何时发生变化时遇到了困难,特别是对于不平衡的树。
谁能指出一种在不使用递归的情况下获取二叉树(不是平衡树或 BST)中节点深度的方法?理想情况下使用 Java/C/C#
节点表示为:
class Node
{
Node Left;
Node Right;
string Value;
int Depth;
}
我的第一个想法是使用带有 FIFO 列表的 Level Order,但我在检测级别何时发生变化时遇到了困难,特别是对于不平衡的树。
您可以使用堆栈实现任何递归方法,这就是递归的工作方式。想象一下你的递归函数看起来像
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);
}
}
}
}
我假设您的意思是填写节点上的深度值,和/或找到最大深度。一种方法是使用两个列表,并按照建议执行级别顺序。它类似于:
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) return level;”。而且,从技术上讲,如果您正在搜索特定值,则不应执行级别顺序遍历,而应使用相关的二叉树属性(例如 val < currentNode.Value goto left else goto right)搜索该值,并跟踪您的深度。如果只给您一个节点并且想要找到它的深度,您需要从根节点对节点执行二进制搜索,或者您需要跟踪节点的父节点。
Here's a simpler solution, I think. If the data structure allowed for an arbitrary number of children, this solution could be easily modified for that case too:
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;
}
这是我提出的最有效的解决方案(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;
}