【问题标题】:Traversing a BST that holds two types of values遍历包含两种类型值的 BST
【发布时间】:2016-12-13 09:41:10
【问题描述】:

对于一个作业,我正在构建一个程序,它将文本文档的单词以及它们在文档中出现的行加载到 BST 中,因此节点有两个数据成员:一个字符串(单词) ,和一个整数队列(单词出现的每一行,都有重复)。 BST 类也是一个模板类。对于作业的其中一个部分,我必须找到出现次数最多的单词并将其打印出来。但是,树是按第一个数据成员(字符串)排序的,所以我知道找到最大长度的队列意味着遍历整个树。不完整包含的私有遍历函数定义具有以下签名:

BinarySearchTree<ItemType, OtherType>::Inorder(void visit(ItemType&, OtherType&), BinaryNode<ItemType, OtherType>* node_ptr) const

所以,我做了这样的功能:

public:
template<class ItemType, class OtherType>
void BinarySearchTree<ItemType, OtherType>::InorderTraverse(void visit(ItemType&, OtherType&)) const
{
   Inorder(visit, root_);
}  // end inorderTraverse

private:
template<class ItemType, class OtherType>
void BinarySearchTree<ItemType, OtherType>::Inorder(void visit(ItemType&, OtherType&), BinaryNode<ItemType, OtherType>* node_ptr) const
{
   if (node_ptr != nullptr)
   {
      Inorder(visit, node_ptr->GetLeftPtr());
      ItemType item = node_ptr->GetItem();
      OtherType other = node_ptr->GetOther();
      visit(item, other);
      Inorder(visit, node_ptr->GetRightPtr());
   }  
} 

所以它传递了一个客户端函数,可以对每个节点的数据成员进行一些操作。但是,我无法找到一种方法来制作一些比较每个节点上的数据成员的函数。我尝试添加两个数据成员来保存相关信息,并在 BST 类中使用一个成员函数并将其传递给 Inorder 函数,但这给了我一个错误,说我正在传递一个“未解析的重载函数类型”。供参考,如下所示:

public:
template<class ItemType, class OtherType>
bool BinarySearchTree<ItemType, OtherType>::GetMaxOther(ItemType& theItem, OtherType& theOther)
{
    if(root_ == nullptr)
        return false; 

    InorderTraverse(MaxOtherHelper);
    theItem = maxOtherItem;
    theOther = maxOther;

    return true;
}

private:
template<class ItemType, class OtherType>
void BinarySearchTree<ItemType, OtherType>::MaxOtherHelper(ItemType& theItem, OtherType& theOther)
{
    if(theOther.Length() > maxOther.Length())
    {
        maxOther = theOther;
        maxOtherItem = theItem;
    }
}

这显然是一个草率的解决方案,而且无论如何它都不起作用。我的问题是,有没有一种方法可以在不创建全新的、非递归的中序遍历函数的情况下完成这项任务?分配带有遍历函数的原型,所以我试图找到是否有办法使用提供的函数来完成。

tl;dr BST 包含两种类型的数据成员,仅按其中一种排序,我如何使用其他的搜索?

【问题讨论】:

  • 我认为不借助全局变量就无法解决这个问题。

标签: c++ binary-search-tree inorder


【解决方案1】:

我不确定您的 BST 解决什么目的。 BST 将数据存储为键值对,其中树按键排序。如果你需要搜索一个值,你必须遍历树或创建一个包含该值的一些信息的新树,以便你可以使用 BST 结构快速获取所需的信息。

另一种解决方案可能是 - 在添加新节点或更新现有节点时,如果您发现该节点的值超过先前最大值的值,则跟踪具有最大出现次数(单词计数)的节点,那么您只需要更改跟踪对象/指针即可。

如果您的要求只是获得出现次数最多的单词,那么您可以使用 Trie,这将比 BST 更有效。

希望对你有帮助!

【讨论】:

    【解决方案2】:

    更有用的 InorderTraverse 签名

    MaxOtherHelper 出现编译错误的原因是它有类型 void(BinarySearchTree&lt;I, O&gt;::*)(I&amp;, O&amp;) 而不是 void(I&amp;, O&amp;)。如果我们实现InorderTraverse如下

    template<class ItemType, class OtherType>
    void BinarySearchTree<ItemType, OtherType>::InorderTraverse(std::function<void(ItemType&, OtherType&)> visit, BinaryNode<ItemType, OtherType>* node_ptr) const
    {
       if (node_ptr != nullptr)
       {
          Inorder(visit, node_ptr->GetLeftPtr());
          ItemType item = node_ptr->GetItem();
          OtherType other = node_ptr->GetOther();
          visit(item, other);
          Inorder(visit, node_ptr->GetRightPtr());
       }  
    } 
    

    这使我们可以更灵活地了解visit 可以是什么,具体来说,我们可以std::bind 或使用 lambda 来传递成员函数并仍然访问this,例如InorderTraverse([this](ItemType &amp; item, OtherType &amp; other){MaxOtherHelper(item, other);});

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-09
      • 1970-01-01
      相关资源
      最近更新 更多