我正在创建一个二进制搜索树模板类,并且想对顺序遍历函数使用函数指针,我对函数指针还可以,但是由于某种原因,一旦代码到位,就无法使用顺序。网上没有其他东西对我有帮助,因此任何反馈都是很棒的。
class Bst
{
struct Node
{
T data;
Node * left;
Node * right;
Node(T key) :data(key), left(nullptr), right(nullptr) {}
};
typedef void(*inorderPtr)(T &);
typedef void(*preorderPtr)(T &);
typedef void(*postorderPtr)(T &);
Node * root;
T & GetItem() const;
void deleteNode(Node*);
void printNode(Node*);
void inorder(Node * root, void (*inorderPtr)(T &)) const;
void preorder(Node * root) const;
void postorder(Node * root) const;
public:
Bst();
~Bst();
Bst(const Bst<T> & source);
const Bst<T> & operator = (const Node &);
void insert(const T);
void print();
void inorder(void(*inorderPtr)(T &)) const;
void printPreorder() const;
void printPostorder() const;
};
基本bst的一些代码如下
template<class T>
inline T & Bst<T>::GetItem() const
{
return data;
}
template<class T>
inline void Bst<T>::inorder(Node * root, void(*inorderPtr)(T &)) const
{
if (root->left != nullptr)
{
inorder(root->left, inorderPtr);
}
inorderPtr(root->GetItem());
if (root->right != nullptr)
{
inorder(root->right, inorderPtr);
}
}
template<class T>
inline void Bst<T>::inorder(void(*inorderPtr)(T &)) const
{
inorder(this->root, inorderPtr);
}
int main()
{
Bst<int> tree;
for (int i = 0; i < 100; i++)
{
tree.insert(i);
}
tree.inorder();
}
主要是基础测试,但是inorder()遇到了麻烦;参数不足
答案 0 :(得分:2)
您需要花费数周的时间来阅读有关C ++的更多信息。请记住, C ++是一种非常困难的编程语言(即使有5年的实践经验,您也不会成为C ++专家;我使用C ++编写代码,但我不是C ++专家;仅在地球上只有几十个)。而且,不要学习任何早于C++11且最好是C++17的东西(因为我们已经在2019年,所以最新的C ++编译器已经兼容C ++ 17,并且所有人都接受C ++ 11;如果您的编译器不了解C ++ 11,请更新您的C ++编译器。
(如果要求您使用C++03或更早的C ++而不是C ++ 11进行编码,则要求加薪,因为那时您使用的是过时的工具。今天,在2019年, C ++ 03中的编码类似于COBOL中的编码:它需要一种具有货币价值的罕见技能。)
因此,首先,读一本不错的C ++书,例如Programming -- Principles and Practice Using C++(由C ++的设计师编写)。然后查看某个C++ reference网站。另请阅读how to debug small programs(在这里非常相关)。
然后编译所有警告和调试信息。如果您的编译器是GCC,请至少使用g++ -Wall -g
进行编译。 您会收到一条很好的诊断消息。请在您的问题中显示它。
最后,您宣布inorder
接受了一个参数,而在调用该参数时却没有给出任何参数(这样做的话前后矛盾):
tree.inorder();
// ^ missing argument
您错误地问:
我正在创建一个二进制搜索树模板类,并且想要使用函数指针
正如我评论的那样,您应该避免使用function pointers (它们非常像C,而不是真正的C ++),并在std::function
type中使用{ inorder
,并在其declaration处传递一些匿名lambda expression。因为从概念上讲,应该传递的不是函数指针,而是call site(它将原始函数指针与数据,封闭值结合在一起),或者,如果不幸的是,您希望避免使用真正的指针。 C ++并与普通的C closure样式和procedural programming兼容,具有calling conventions,因此不仅传递原始函数指针,还传递一些客户端数据。
所以您真的想声明和定义(就像大多数callbacks一样)
template<class T>
inline void Bst<T>::inorder(std::function<void(T&)> fun) const;
(后来,作为优化,您可以将fun
作为const
C++ containers传递),并且可以像使用lambda表达式那样使用它,例如:
tree.inorder([](T& x) { std::cout << x << std::endl; });
我声称您的老师应该首先教您有关闭包的知识,以及如何以某种reference风格(在您的情况下很自然)很好地使用闭包,然后解释其实现以及以后,教功能指针。在大多数情况下,函数指针在C ++中已作废(但为了与C和C ++的过时版本兼容而存在)。
PS。您不了解的内容要花几十页来解释(因为C ++ functional programming非常复杂)。我们这里没有足够的空间(和时间来写它)。请花一个星期阅读一本优秀的C ++书。
答案 1 :(得分:2)
假设您要打印树中每个节点的值:
void value_printer(int& value)
{
std::cout << "Value is " << value << '\n';
}
int main()
{
Bst<int> tree;
// Insert nodes...
tree.inorder(&value_printer);
}
您在value_printer
调用中将指针传递到inorder
函数。然后将为遍历中的每个节点调用该函数。
传递指针的函数当然可以做其他事情。而且,正如目前所声明的那样,您甚至可以修改树的值。
详细了解std::function
和lambda expressions。另请参见this答案。