在BST中,在O(log N)中找到小于/大于给定节点的节点数?

时间:2014-08-11 19:57:22

标签: algorithm binary-search-tree

给定BST(二进制搜索树),如何计算O(log N)中比给定节点更小/更大的节点数。 假设您可以修改节点以向其中添加更多变量,并且在构建树时,只要它们小于O(n ^ 2)就可以执行操作。

此外,它还有助于提供图片以显示应考虑哪些子树。

2 个答案:

答案 0 :(得分:2)

这是增强搜索树的经典用法。基本上,您通过为每个节点添加父指针来增加BST,以及每个节点下的子节点总数(在构建树时可以执行此操作,而无需额外的渐近成本)。

要解决此问题,请计算给定节点左子树下的子节点总数(常数时间,因为您只需在增强树数据中查找)。然后,将父指针移向根。在每个父级,如果您来自正确的子树,请将左子树子计数添加到总计数中。

因为你的树是平衡的,所以当你走到根时,你只会做O(log n)工作。

答案 1 :(得分:0)

如果您可以存储每个节点的子树权重,则可以在(log n)中进行(一次搜索目标)。
搜索您的目标并计算权重,

代码

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

void search_tree(node* root, int key){

bool found = false;
node* tmp = root;
int greaterCount, smallerCount;
greaterCount = smallerCount = 0;

while (!found && tmp != nullptr){

    if (key < tmp->value){
        // +1 for tmp it self
        greaterCount += tmp->rightWeight + 1;
        tmp = tmp->left;
    }
    else if (key > tmp->value){
        // +1 for tmp it self
        smallerCount += tmp->leftWeight + 1;
        tmp = tmp->right;
    }
    else {
        // found
        found = true;           
        smallerCount += tmp->leftWeight;
        greaterCount += tmp->rightWeight;
    }
}

// If element isn't found , you can delete this
if (!found){
    cout << "targer not found" << endl;
    return;
}

cout << "Elements greater than " << key << ": " << greaterCount << endl
     << "Elements smaller than " << key << ": " << smallerCount << endl;

}

int main() {

/*
    Tree

    .....................(10)........................
    .................../.....\.......................
    .................(5).....(20)....................
    .............../...\..../....\...................
    .............(4)..(8)..(11)...(40)...............
    ............/.............\......................
    ...........(1)............(12)....................


*/


//Left subtree
node* n1 = new node(1, nullptr, nullptr, 0, 0);
node* n4 = new node(4, n1, nullptr, 1, 0);
node* n8 = new node(8, nullptr, nullptr, 0, 0);
node* n5 = new node(5, n4, n8, 2, 1);

//Right subtree
node* n12 = new node(12, nullptr, nullptr, 0, 0);
node* n11 = new node(11, nullptr, n12, 0, 1);
node* n40 = new node(40, nullptr, nullptr, 0, 0);
node* n20 = new node(20, n11, n40, 2, 1);

// Root
node* n10 = new node(10, n5, n20, 4, 4);

search_tree(n10, 12);

return 0;
}

详细

我假设已经创建了树(您可以在插入节点时更新权重), 每当你进入节点并且它不是你的目标,检查它是否比你的目标更重要或更小 如果它更大,则此节点的右子树也将比目标更大,然后更新greaterCount 如果节点小于目标,则使用左子树进行相同的操作。