如何在 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-&gt;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”分支中交换了 leftright。 但是,如果值看起来相等,则执行控制将在两个位置转到“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++ 中的类中递归调用函数方法?的主要内容,如果未能解决你的问题,请参考以下文章

递归打印类中的链表c ++

如何在 C++ 中调用父类中的函数? [复制]

如何在另一个类中使用带有构造函数的类?

从外部类 C++ 正确调用嵌套类中的函数

我可以在所述类中调用我的函数中的类吗?

java中,当实例化子类时会递归调用父类中的构造方法。这个说法对么?为啥