繁体   English   中英

二叉搜索树 - 使用成员函数通过 inOrder 遍历查找第 n 个项目

[英]Binary Search Tree - Find nth Item with inOrder traversal using a member function

我需要遍历二叉搜索树并找到第 n 项,我能够成功遍历树,但是当我尝试实现限制或端点以在第n项处停止时——返回其值,我无法让我的计数器递增。 我已经尝试了大约 50 种不同的方法来使计数器增加但无济于事。

我目前将计数器实现为类属性,因此它仍然在递归函数的单个调用范围之外。 为了帮助我进行故障排除和学习,我尝试让它打印出节点处的值以及位置,这就是我意识到我的计数器不会增加的方式。

想要的结果:

10 (position 1)
25 (position 2)
32 (position 3)
...

当前结果:

10 (position 1)
25 (position 1)
32 (position 1)
...

这是我的课:

class BST {
  public:
  int data;
  int counter = 0;
  BST *left, *right;
  BST();
  BST(int);
  ~BST();
  void insert(int val);
  int nth_node(int n);
  int size();
};

以及我的 nth_node 函数:

int BST::nth_node(int n) {
    
    /*
    // Check to see if we've hit the limiter.
    if (counter == n) {
        std::cout << std::endl<< std::endl << "ITEM FOUND!!!" << std::endl<< std::endl;
        counter = 0; //reset the counter
        return data;
    } */
    
    if (counter <= n) { // Haven't hit the limiter, so do in_order transversal
    
        // Go left
        if (left != nullptr){
            left -> nth_node(n);
        }
        
        // Go middle
        counter++;
        std::cout << data << " (position: " << counter << "), " << std::endl ;
        
        // Go Right
        if (right != nullptr){
            right -> nth_node(n);
        }
    }
    
    
    return data;
}

使用树的一个节点的成员变量是行不通的。 不同的节点有不同的计数器变量。 在您的代码中,每个计数器变量最多减少一次,更糟糕的是它从未初始化,导致未定义的行为。

您需要在此处引入一个辅助函数,除非您想先查询子树,然后可能递归调用同一子树的函数。

注意:下面的示例假设n是基于 1 的,即 1 用于获取最小值 2,表示第二小的值,等等。


您可以通过引用辅助函数来传递n 通过这种方式,您可以为每个递归调用的成员函数中声明的变量(参数)使用“别名”。

namespace
{

    /**
     * \param[in,out] n     in: the 1 based index of the node to find;
     *                     out: the original value minus the number of nodes searched
     * 
     * \return nullptr, if not found, the node found otherwise 
     */
    BST const* NthElementHelper(BST const& tree, int& n)
    {
        int size = 1;
        
        if (tree.m_left != nullptr)
        {
            auto leftResult = NthElementHelper(*tree.m_left, n);
            if (leftResult != nullptr)
            {
                // node found in left subtree
                return leftResult;
            }
        }
        
        if (n == 1)
        {
            return &tree;
        }
        --n;
        
        if (tree.m_right != nullptr)
        {
            return NthElementHelper(*tree.m_right, n);
        }
        return nullptr;
    }
}

int BST::nth_node(int n)
{
    if (n <= 0)
    {
        throw std::runtime_error("n needs to be positive");
    }

    auto findResult = NthElementHelper(*this, n);
    if (findResult == nullptr)
    {
        throw std::runtime_error("there are no n nodes in the tree");
    }
    return findResult->m_data;
}

或者,您可以根据是否找到节点返回节点或子树大小:

namespace
{

    std::variant<BST const*, int> NthElementHelper(BST const& tree, int n)
    {
        int size = 1;
        
        if (tree.m_left != nullptr)
        {
            auto leftResult = NthElementHelper(*tree.m_left, n);
            if (leftResult.index() == 0)
            {
                // node found
                return leftResult;
            }
            auto subtreeSize = std::get<int>(leftResult);
            size += subtreeSize;
            n -= subtreeSize;
        }
        
        if (n == 1)
        {
            return &tree;
        }
        --n;
        
        if (tree.m_right != nullptr)
        {
            auto rightResult = NthElementHelper(*tree.m_right, n);
            if (rightResult.index() == 0)
            {
                return rightResult;
            }
            auto subtreeSize = std::get<int>(rightResult);
            size += subtreeSize;
        }
        return { size };
    }
}

int BST::nth_node(int n)
{
    if (n <= 0)
    {
        throw std::runtime_error("n needs to be positive");
    }

    auto findResult = NthElementHelper(*this, n);
    if (findResult.index() != 0)
    {
        throw std::runtime_error("there are no n nodes in the tree");
    }
    return std::get<BST const*>(findResult)->m_data;
}

您可以将 counter 作为函数参数,并为方便起见设置默认值:

int BST::nth_node(int n, int counter = 0)
{
    
    /*
    // Check to see if we've hit the limiter.
    if (counter == n) {
        std::cout << std::endl<< std::endl << "ITEM FOUND!!!" << std::endl<< std::endl;
        counter = 0; //reset the counter
        return data;
    } */
    
    if (counter <= n) { // Haven't hit the limiter so do in_order transversal
    
        // Go left
        if (left != nullptr){
            left -> nth_node(n, counter);
        }
        
        // Go middle
        counter++;
        std::cout << data << " (position: " << counter << "), " << std::endl ;
        
        // Go Right
        if (right != nullptr){
            right -> nth_node(n, counter);
        }
    }
    
    
    return data;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM