【问题标题】:Binary Search Tree - Find nth Item with inOrder traversal using a member function二叉搜索树 - 使用成员函数通过 inOrder 遍历查找第 n 个项目
【发布时间】:2021-12-04 03:02:54
【问题描述】:

我需要遍历二叉搜索树并找到第 n 个项目,我能够成功地遍历树,但是当我尝试实现限制或端点时,停止在 nth 项目 -返回它的值,我不能让我的计数器增加。我已经尝试了大约 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;
}

【问题讨论】:

    标签: c++ data-structures binary-tree binary-search-tree recursive-datastructures


    【解决方案1】:

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

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

    注意:以下示例假设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;
    }
    

    【讨论】:

      【解决方案2】:

      您可以将 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;
      }
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-09
        • 1970-01-01
        • 2019-04-09
        相关资源
        最近更新 更多