【问题标题】:Floor Value of an element in a Binary Search Tree二叉搜索树中元素的下限值
【发布时间】:2020-08-02 10:45:50
【问题描述】:

所以我正在阅读 Narasimha Karumanchi 所著的《轻松实现数据结构和算法》一书,其中给出了 bst sn-p 的底值 - BST 章中的第 61 题。 sn-p 让我非常困惑,现在我只想知道它是如何工作的: sn-p如下:

node* floorValue(node* root, node* prev ,int k)
{
    if(!root){
        return NULL;
    }

    if( !(floorValue(root->left , prev ,k))
    {
        return 0;
    }
    if(root->data == k)
    {
        return root;
    }
    if(root->data > k)
    {
        return prev;
    }
    prev = root;
    return floorValue(root->right , prev , k);
}

在此,node* prevNULL 启动,用于存储前一个节点,int k 是我们要为其查找下限值的整数。

有人可以帮助我理解它的递归吗?我很困惑,因为:

1 .代码: if( !(floorValue(root->left , prev ,k)) { return 0; } 当树的最左边的元素被命中时将返回 0。但这会触发所有递归调用返回 0。

  1. 为什么当我们返回 node* 而不是任何 int 时它返回 0

我们将不胜感激。我已经解决了这个问题,但它没有使用这种方法,而是一种更直接的方法(根据我的说法)。我想知道我做错了什么或者我在这段代码中遗漏了什么。

输入: 第一个输入将是节点数: 接下来的 n 行将是节点数据。 n 之后的第一个输入将是根值。

完整代码:

#include<bits/stdc++.h>
using namespace std;

struct node
{
  int data;
  node* left;
  node* right;
};

node* insertBST(node* root , int x)
{

    if(root==NULL)
    {
        node* root= new node;
        root->data = x;
        root->left = root->right = NULL;
        return root;
    }
    else
    {
        if(x <root->data)
        {
            root->left = insertBST(root->left , x);
        }
        else
        {
            root->right = insertBST(root->right , x);
        }

    }
}

void inorder(node* root)
{
    if(root)
    {
        inorder(root->left);
        cout<<root->data<<" ";
        inorder(root->right);
    }
}

node* floorValue(node* root, node* prev ,int k)
{
    if(!root){
        return NULL;
    }

    if( !(floorValue(root->left , prev ,k))
    {
        return 0;
    }
    if(root->data == k)
    {
        return root;
    }
    if(root->data > k)
    {
        return prev;
    }
    prev = root;
    return floorValue(root->right , prev , k);
}
int main()
{
    int n;
    cin>>n;
    node *root = new node;
    root = NULL;
    for(int i = 0 ;i<n;i++)
    {
        int k;
        cin>>k;
        root= insertBST(root , k);
    }

    inorder(root);
    
    cout<<"\nEnter the Value for which floor has to be searched : ";
    int k;
    cin>>k;
    
    node* prev = NULL;
    cout<<floorValue(root , prev, k);
    return 0;
}


除了一些变量名之外,代码与书中给出的完全相同。

谢谢你,提前致谢。

【问题讨论】:

  • prev的初始值是多少?
  • @YashShah 它是 NULL。
  • “元素的底值”是什么意思?如果它只是二叉搜索树中的最小值,那只是在树上向左移动直到到达叶节点。
  • @PaulMcKenzie,我猜是这样的:对于具有元素 1、3、5、7 和给定值 4 的给定 BST,返回 3。
  • 所以它基本上是一个中序遍历,并保存最后访问节点的值并将其与测试值进行比较。这就是它归结为的内容以及当前代码似乎在做什么。代码除了返回NULL0而不是nullptr等C++相关问题外,还有什么基本没被代码理解?

标签: c++ algorithm data-structures binary-search-tree


【解决方案1】:

您发现的 sn-p 很糟糕,但您的问题的答案是 return 0return NULL 相同——它不是整数,而是空指针。如果树中没有节点

这是一个更好的实现:

Node* floorNode(Node* tree, int k) {
    Node *flr = NULL;
    while(tree) {
        if (tree -> data <= k) {
            flr = tree;
            tree = tree->right;
        } else {
            tree = tree->left;
        }
    }
    return flr;
}

【讨论】:

  • 是的,我知道,但那是在一本书中给出的,所以我问了。我以为我错过了一些东西。我已经使用与您给出的相同方法解决了这个问题。谢谢你的回答。
【解决方案2】:

这是经典的二分搜索算法。我总是建议您了解您发布的问题。如果您了解算法,您将了解二进制搜索的实际工作原理,以及使用系统/计算机内存的 StackTrace 进行回溯的工作原理。

让我们深入研究一下。 :)

if(!root){
    return NULL;
}

上面的代码sn-p,就是这样,如果你到达这里,保证你搜索了所有的可能性,但没有找到你想要的'钥匙'。 :(

if( !(floorValue(root->left , prev ,k))
{
    return NULL; 
}

请记住,您应该返回 NULL,而不是返回 0,因为您的函数的返回值实际上是 NULL,(尽管 0/NULL 都定义了 c/c++ 中的错误情况,但您可以过早地使用它。

现在您可以看到,您正在深入到函数中,root->left 表示首先检查 Tree 的左侧,类似于 Binary Search,您正在搜索输入元素的左侧。

if(root->data == k)
{
    return root;
}

如果你到达这里,恭喜你,你终于到达了你的目的地 :D,换句话说,你发现你的结果是在巨大的(或小的,随便的)输入元素中。

if(root->data > k)
{
    return prev;
}

当你的中间元素大于你的键时,上面的片段是相同的,所以你知道你必须去输入的左边。 (往好的方向总是会给你带来悲伤,你最终会一无所有)。

 prev = root;
return floorValue(root->right , prev , k);

上面的代码告诉你,你向左走,结果是0(你最终找不到结果),所以你现在需要向右走。

现在最重要的是,了解下面这两个sn-ps ::

if(root->data > k)
{
    return prev;
}

 prev = root;
 return floorValue(root->right , prev , k);

以上两个 sn-ps 不仅让您深入到树(或输入)的左侧或右侧部分,而且还检查左侧树的每个左右节点,以及右侧树的右侧和左侧。

当它未能获得你想要的钥匙时,它会回到你开始进入 LEFT 的地方(这是一种黑暗系列,让我们假设 left 在这里是过去,:D 对吗??)现在你必须去到未来,没错,就是找出钥匙。

你拿到钥匙了吗?从左侧(过去)返回,或再次向右(未来)返回。

你肯定会得出结论,要么成功,要么失败。

享受吧。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 2012-11-25
    相关资源
    最近更新 更多