Для назначения я создаю программу, которая загружает слова текстового документа в 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 содержит два типа элементов данных, сортируется только по одному из них, как мне искать, используя другие?
Я не уверен, какую цель решает ваш BST. BST хранит данные в виде пары «ключ-значение», где дерево сортируется по ключам. Если вам нужно найти значение, вы должны пройти по дереву или создать новое дерево, которое содержит некоторую информацию о значении, чтобы вы могли использовать структуру BST для быстрого получения необходимой информации.
Другое решение может быть — отслеживать узел, который имеет вхождение (количество слов) максимум, при добавлении нового узла или обновлении существующего узла, если вы обнаружите, что значение этого узла превышает значение предыдущего максимума, то вы просто необходимо изменить объект отслеживания / указатель.
Если ваше требование состоит только в том, чтобы получить слово с максимальным появлением, то вы можете использовать Trie который будет более эффективным, чем BST для этой цели.
Надеюсь, поможет!
Причина, по которой у вас ошибка компиляции MaxOtherHelper
это то, что он имеет тип
void(BinarySearchTree<I, O>::*)(I&, O&)
и не void(I&, O&)
, Если мы реализуем 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
или использовать лямбду для передачи функций-членов и по-прежнему доступ this
например, InorderTraverse([this](ItemType & item, OtherType & other){MaxOtherHelper(item, other);});