如何在 c++ 的类中递归调用函数方法?

How to call a function method recursively in classes in c++?

本文关键字:调用 递归 函数 方法 c++      更新时间:2023-10-16

所以,不久前我开始学习和阅读OOP,我一直在使用类和对象实现我所知道的所有数据结构,只是为了整体练习和习惯在c ++中使用OOP。

我正在实现树数据结构,我一直想知道如何递归调用方法(我知道我必须传入一个参数(,以便当我在 main 中创建一个对象并调用特定方法时,它写得像下面的a.inorder();而不是a.inorder(root),因为 root 是一个私有属性。

这可能吗?

我的代码:

#include<iostream>
using namespace std;
struct node
{
int data;
node* left;
node* right;
};
class tree
{
private:
node* root;
public:
tree();
tree(int val);
void insert(int val);
void preorder();
void postorder();
void inorder();
int count();
};
tree::tree() : root { NULL }
{
}
tree::tree(int val)
{
root = new node;
root->data = val;
root->left = root->right = NULL;
}
void tree::insert(int val)
{
if (!root)
{
root = new node;
root->data = val;
root->left = root->right = NULL;
}
else
{
node* t = root;
node* p = NULL;
while (t)
{
p = t;
if (val > root->data)
t = root->right;
else
t = root->left;
}
t = new node;
t->data = val;
t->left = t->right = NULL;
if (p->data > t->data)
p->left = t;
else
p->right = t;
}
}
void tree::preorder()
{
if (root)
{
}
}

在你的设计中,node指的是它自己。由于递归对象node,因此您可以在node上定义递归方法:

struct node
{
int data;
node* left;
node* right;
void preorder() {
//...
left->preorder();
right->preorder();
}
};

然后,tree::preorder()只会向root->preorder()发出一个电话。

编写一个私有静态递归函数,将指向根节点的指针传递给它,并从相应的公共非静态成员函数调用该函数。

例如

public:
std::ostream & preorder( std::ostream &os = std::cout ) const
{
return preorder( root, os );
}
//...
private:
static std::ostream & preorder( const node *root, std::ostream &os );
//...

这是一个评论而不是实际的答案,因为它解决的问题与您询问的问题不同。但是,对于评论空间来说太长了,这就是我在这里发布它的原因。

我想你在这一部分中错误地提到了root

while (t)
{
p = t;
if (val > root->data)
t = root->right;
else
t = root->left;
}

恕我直言,它应该看起来像这样:

while (t)
{
p = t;
if (val > t->data)
t = t->right;
else
t = t->left;
}

此外,将要查找插入位置的代码与进行实际插入的代码进行比较:

if (p->data > t->data)
p->left = t;
else
p->right = t;

您以相反的顺序放置了一个比较子表达式 - 在查找时,您测试新值是否大于现有节点中的值,但在插入时,您测试现有值是否大于新值。如果它们不同,代码将正常工作,因为您还交换了"then"和"else"分支中的leftright
但是,如果值看起来相等,则执行控件将在两个位置转到"else"。因此,测试代码可能会在空指针left停止,但随后会将一个新节点附加到right,该节点未被测试为NULL

为什么tree类会对node进行内部操作?node类最了解node的内部结构,所以让它自己初始化。这也将帮助您坚持 DRY 原则,间接坚持 KISS 原则以及单一责任原则。

结构节点 { 整数数据; 节点* 左; 节点* 右; node(int val( : data(val(, left(NULL(, right(NULL( {}        }; 类树 { 私人: 节点* 根; 公共: 树((; 树(int val(; 空隙插入(int val(; }; 树::树(( : 根 { 空 } { } 树::树(int val( : 根(new node(val(( { } 空树::插入(整数值( { 如果(!根( { 根 = 新节点(val(; } 还 { 节点* t = 根; 节点* p = 空; 而 (t( { p = t; 如果(数据( t = t->左; 还 t = t->右; } t = 新节点(val(; 如果(t->数据数据( p->左 = t; 还 p->右 = t; } }

此外,您也可以使insert递归。

结构节点 { 整数数据; 节点* 左; 节点* 右; node(int val( : data(val(, left(NULL(, right(NULL( {}        }; 类树 { 私人: 节点* 根; 公共: 树((; 树(int val(; 空隙插入(int val(; 保护: void insertat(node* p, int val(; }; 空树::插入(整数值( { 如果(!根( 根 = 新节点(val(; 还 插入(根,瓦尔(; } void tree::insertat(node* t, int val(; { 如果(数据( { 如果(T->左( 插入(T->左,瓦尔(; 还 t->left = new node(val(; } 还 { 如果(T->右( 插入(t->右,瓦尔(; 还 t->right = new node(val(; } }