我为计算我为任务编写的函数的时间复杂性而遇到了一些麻烦。
此函数是递归的,它计算二进制搜索树中有多少值大于10的叶子。这是功能:
int count_leaf(node* root)
{
static int count = 0;
int call;
if (root == NULL)
{
return 0;
}
call = count_leaf(root->left);
if (root->left == NULL && root->right == NULL && root->data > 10)
{
count++;
}
call = count_leaf(root->right);
return count;
}
计算此功能的时间复杂度的最正确和最恰当的方法是什么?
答案 0 :(得分:2)
它只触及树的每个节点一次,因此会有n
次调用,使其成为O(n)
。
答案 1 :(得分:1)
由于您需要访问所有节点,因此复杂性实际为O(n)
。这比与二叉树相关联的O(n*log n)
更好。它也是渐近最优的。
直接从父节点而不是从根节点访问子节点,对于每个子节点都是如此,并且以这种方式访问子节点是一个恒定时间操作。随着遍历的完成,所有n
个节点都已被访问过。
答案 2 :(得分:1)
通过实验来衡量算法实现的复杂性的一种简单方法是将计数器放在函数的开头或用于迭代的循环。对于您的示例,如下所示:
int test_count = 0;
int count_leaf(node* root)
{
static int count = 0;
int call;
++test_count;
// ...
}
然后在运行测试后打印出test_count
的值。如果你使用不同的测试集进行实验(使每个集的大小是前一个的两倍,以使差异明显),你将得到一个很好的指标,即算法是O(1),O(n),O(n ^ 2)等。
另一种方法是使用简单的计时器来测量测试运行的持续时间。比较运行算法的时间与几个大小加倍的数据集。处理每个数据集的时间差异将为您提供算法计算复杂性的指示。有关几个例子,请参阅Sedgewick的“算法”第4版,第1.4节。
显然这些不是证据,也可能不适用于大多数作业答案 - 但它可以帮助您确保获得正确的作业答案。