[英]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.