我怎么可能更快地搜索排序的二叉树?

时间:2019-02-25 14:56:13

标签: c++ performance

由于我已经使用一年多了,所以我正尝试重新使用C ++。

我正在以下网站上尝试作业:www.testdome.com

当前,我的任务是在排序的二叉树中找到一个值。我应该使用的Node类看起来像这样:

class Node
{
public:
    Node(int value, Node* left, Node* right)
    {
        this->value = value;
        this->left = left;
        this->right = right;
    }

    int getValue() const
    {
        return value;
    }

    Node* getLeft() const
    {
        return left;
    }

    Node* getRight() const
    {
        return right;
    }

private:
    int value;
    Node* left;
    Node* right;
};

我完成了任务,并提出了两个实现。我在上一次测试中都遇到了一个错误:超过了时间限制

我想知道如何更快地编写它。我的实现:

1。使用std::stack处理所有节点

我将嵌套节点保存在std::stack中,并遍历它们直到获得一个值。我认为这应该是正确的解决方案,避免真正的递归。

bool containsStdStack(const Node& root, int value)
{
    std::stack<const Node*> queue;
    queue.push(&root);

    while(!queue.empty()) {
        const Node*const tmp = queue.top();
        queue.pop();

        if(tmp->getValue() == value) {
            return true;
        }
        // Do not push nulls to avoid extra iterations
        if(const Node* left = tmp->getLeft()) {
            queue.push(left);
        }
        if(const Node* right = tmp->getRight()) {
            queue.push(right);
        }
    }
    return false;
}

2。天真的递归方法

由于以上方法均未通过性能测试,因此我尝试了这种幼稚的方法-简单的解决方案往往比预期的要快。

bool containsRecursive(const Node&root, int value) {
    return containsRecursive(&root, value);
}
bool containsRecursive(const Node*root, int value) {
    return root!=nullptr &&(
        root->getValue() == value
        || containsRecursive(root->getLeft(), value)
        || containsRecursive(root->getRight(), value)
    );
}

但是它仍然没有通过性能测试。

我错过了重要的事情吗?也许性能测试真的很苛刻?是否可以在没有黑客的情况下进一步优化?

2 个答案:

答案 0 :(得分:5)

您的递归方法是一个不错的开始,但是考虑到树已排序,它可以访问(最多)每个节点

在每个阶段,只需根据当前节点小于还是大于子节点,在左边子树 或在右边子树 您要查找的节点。

所以:

  • 当前节点是否匹配?大!完成了。
  • 它太高了吗?往下看左边的子树(其中的所有内容都应该“少”)
  • 太低了吗?往下看右边的子树(所有内容都应该是“更多”)
  • 我们选择的子树是否为空/不存在? !哪里都没有比赛。完成了。

这将您的算法从线性更改为对数,因为每次好的树搜索都应如此。 :)

这就是std::map使用小于比较器进行工作的原因。您也可以从中得出相等性(对于x==y => !(x < y) && !(y < x)持有的那些值)。

答案 1 :(得分:1)

我假设树已排序。话虽如此,我只是在检查是否需要在树的左侧或右侧搜索值。搜索复杂度是对数的。

bool containsRecursive(const Node&root, int value) {
    return containsRecursive(&root, value);
}
bool containsRecursive(const Node*root, int value) {
    // root is null  
    if (root == NULL) return false;

    // value is present at root 
    if(root->getValue()== value) return true;


    // value is greater than root's value //this saves lot of time
    if (root->getValue() < value) 
       return containsRecursive(root->getRight(), value); 

    // value is smaller than root's key 
    return containsRecursive(root->getLeft(), value); 
}