我试图以递归方式计算O(log n)时间内任何(不一定是完整的)BST的深度。
这是我提出的算法:
//max() - returns the max of two numbers
int depth(root)
{
if(root->left==NULL && root->right==NULL) //leaf
return 0;
else if(root->left!=NULL && root->right==NULL) //with right leaf
return( max(depth(root->left),0)+1);
else if(root->left==NULL && root->right!=NULL) //with left leaf
return( max(0,depth(root->right)+1);
else if(root->left->left==NULL && root->left->right==NULL && root->right->left==NULL&&root->right->right==NULL) // this a parent of two leaves
return 1;
else// for the condition that this a parent of two sub roots
return( max(depth(root->right),depth(root->left))+1);
}
这个算法在O(log n)时间内计算深度是否合适?
有更好的方法吗?
答案 0 :(得分:7)
这是O(n)时间,因为你可以遍历每个节点。您可以在O(log n)中搜索二进制搜索树,但除非在构建深度或执行类似操作时缓存深度,否则无法在O(n)中找到二叉树的深度。
您可能需要注意两种特殊情况。
完美二叉树可以在O(log n)中确定其深度。这意味着每片叶子处于同一水平。
完整和平衡二叉树的深度近似在O(log n)或O(1)中如果数量为节点是已知的。这将是近似值(通常为+/- 1)。
答案 1 :(得分:2)
你获得O(log(n))运行时的唯一方法就是你只检查一条路径,而你能够通过检查一条路径的唯一方法是你知道树有统一的高度,这只是完整二叉树的情况,你的问题具体说明并非如此。
因此,没有O(log(n))算法可以确定给定二叉树的深度。
答案 2 :(得分:2)
通过查看每个叶子节点,您只能找到未知的非平衡树的最深节点,这需要您正在进行遍历 - O(n)。
至于“更好”的方式,你不能把它作为一个较小的顺序,但你不需要这么复杂的代码来实现你的结果。这是一个效率稍低的实现(因为它更深层次地递归),它更具可读性和更强大(如果你传入一个NULL根指针它不会弹出)方法:
int depth(root)
{
if (root == NULL)
return(0);
return(1 + max(depth(root->left), depth(root->right)));
}
答案 3 :(得分:1)
C中的一个问题是函数堆栈没有在堆上动态分配,所以在某一点上我们将耗尽空间。特别是当每个递归调用产生两个函数时。换句话说,如果你的树有点平衡,你最终会得到log(N)^ 2函数调用。如果您改为迭代左侧分支并递归右侧分支,则堆栈将不会快速增长。
int
depth(struct bt *root, int dl)
{
int dr, dmr;
for(dmr=dr=dl; root != NULL; dl++){
if((dr = depth(root->right, dl+1)) > dmr)
dmr = dr;
root = root->left;
}
return(dl > dmr ? dl : dmr);
}
这是I.E.的方式。 Quick Sort在许多操作系统中实现:
答案 4 :(得分:0)
int maxDepth(BST *root)
{
int ldepth=0,rdepth=0,maxdepth=0;
if(root==NULL)
return(0);
ldepth=maxDepth(root->left);
rdepth=maxDepth(root->right);
maxdepth=MAX(ldepth,rdepth);
return(maxdepth+1);
}
答案 5 :(得分:0)
int TreeDepthRec(Tree *pt){
if(!*pt)
return 0;
int a = TreeDepthRec(&(*pt)->left);
int b = TreeDepthRec(&(*pt)->right);
return (a>b)? 1+a : 1+b;
}
我认为比较两个整数变量比调用函数花费的时间更少。