如何在 C++ 中的类中递归调用函数方法?
Posted
技术标签:
【中文标题】如何在 C++ 中的类中递归调用函数方法?【英文标题】:How to call a function method recursively in classes in c++? 【发布时间】:2020-06-18 20:30:29 【问题描述】:所以,不久前我开始学习和阅读 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)
【问题讨论】:
⟼请记住,尤其是在 Stack Overflow 上学习和提问时,尽可能让代码保持井井有条是很重要的。 Consistent indentation 有助于传达结构,更重要的是,有助于传达意图,这有助于我们快速找到问题的根源,而无需花费大量时间尝试解码正在发生的事情。 如果一个类有一个像root
这样的属性,那么将它传递给一个函数是多余的,这个类已经知道它是什么了。对于递归,您始终可以使用单独的 protected
方法进行挖掘,然后根据需要使用它。
indirection 是你的朋友...从该方法调用另一个执行递归的 [private] 方法
“我知道我必须传入一个参数” - 在一个类中,每个(非静态)方法属性都会自动传递一个“this”指针。在某些递归工作中,隐藏指针就足够了。
【参考方案1】:
在您的设计中,node
指的是它自己。由于是递归的node
对象,你可以在node
上定义递归方法:
struct node
int data;
node* left;
node* right;
void preorder()
//...
left->preorder();
right->preorder();
;
然后,tree::preorder()
只会向root->preorder()
发送呼叫。
【讨论】:
【参考方案2】:编写一个私有静态递归函数,将指向根节点的指针传递给它,并从相应的公共非静态成员函数中调用该函数。
例如
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 );
//...
【讨论】:
【参考方案3】:这是评论而非实际答案,因为它解决的问题与您所询问的问题不同。不过评论区太长了,所以才放在这里。
我想你在这部分错误地引用了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”分支中交换了 left
和 right
。
但是,如果值看起来相等,则执行控制将在两个位置转到“else”。因此,测试代码可能会在空的left
指针处停止,但随后会在right
上附加一个新节点,而NULL
并未经过测试。
【讨论】:
【参考方案4】:为什么tree
类会对node
执行内部操作? node
类最了解node
的内部结构,所以让它自己初始化。这也将帮助您坚持使用DRY principle,并间接地使用KISS principle,以及Single-responsibility principle。
结构节点 整数数据; 节点*左; 节点* 对; 节点(int val):数据(val),左(NULL),右(NULL) ; 类树 私人的: 节点*根; 上市: 树(); 树(int val); 无效插入(int val); ; 树::树() : 根 NULL 树::树(int val) : 根(新节点(val)) 无效树::插入(int val) 如果(!根) 根=新节点(val); 别的 节点* t = 根; 节点* p = NULL; 而 (t) p = t; 如果(val 数据) t = t->左; 别的 t = t->对; t = 新节点(val); 如果(t-> 数据 数据) p->左 = t; 别的 p->右=t;
此外,您也可以使 insert
递归。
结构节点 整数数据; 节点*左; 节点* 对; 节点(int val):数据(val),左(NULL),右(NULL) ; 类树 私人的: 节点*根; 上市: 树(); 树(int val); 无效插入(int val); 受保护: 无效插入(节点* p,int val); ; 无效树::插入(int val) 如果(!根) 根=新节点(val); 别的 插入(根,val); 无效树::插入(节点* t,int val); 如果(val 数据) 如果(t->左) insertat(t->left, val); 别的 t->left = 新节点(val); 别的 如果(t-> 右) insertat(t->right, val); 别的 t->right = 新节点(val);
【讨论】:
以上是关于如何在 C++ 中的类中递归调用函数方法?的主要内容,如果未能解决你的问题,请参考以下文章