Как рекурсивно вызвать метод функции в классах в с ++? - PullRequest
2 голосов
/ 18 июня 2020

Итак, я начал изучать и читать о OOP не так давно, а go, я реализовал все структуры данных, которые я знаю, используя классы и объекты только для общей практики и для того, чтобы привыкнуть к использованию OOP в c ++.

Я реализую древовидную структуру данных, и мне было интересно, как вызвать метод рекурсивно (я знаю, что мне нужно передать аргумент), чтобы при создании объекта в main и вызовите специальный метод c, который написан следующим образом 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)
    {

    }
}

Ответы [ 4 ]

2 голосов
/ 19 июня 2020

В вашем дизайне node относится к самому себе. Поскольку это рекурсивный объект node, вы можете определить рекурсивный метод для node:

struct node
{
    int data;
    node* left;
    node* right;

    void preorder() {
        //...
        left->preorder();
        right->preorder();
    }
};

И затем tree::preorder() просто отправит вызов root->preorder().

1 голос
/ 19 июня 2020

Это комментарий, а не реальный ответ, поскольку он касается другой проблемы, чем вы спрашиваете. Однако он слишком длинный для места для комментариев, поэтому я размещаю его здесь.

Я полагаю, вы ошибочно ссылаетесь на 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;

Вы поместили подвыражения сравнения в обратном порядке - при поиске вы проверяете, больше ли новое значение, чем в существующем узле, но при вставке вы проверяете, больше ли существующее значение, чем новое. Если они отличаются, код будет работать нормально, потому что вы также поменяли местами left и right в ветвях then и else.
Однако, если значения кажутся равными, контроль выполнения будет go в "else" в обоих местах. В результате код тестирования может остановиться на пустом указателе left, но тогда к right будет добавлен новый узел, который не был протестирован на предмет NULL.

1 голос
/ 18 июня 2020

Напишите частную рекурсивную функцию c, передавая ей указатель на узел root, и вызовите функцию из соответствующей функции-члена publi c non-stati c.

Для например

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 );
    //...
0 голосов
/ 24 июня 2020

Почему класс tree должен выполнять операции intrinsi c с node? Класс node лучше всех знает внутреннюю структуру node, поэтому пусть он инициализируется сам. Это также поможет вам придерживаться принципа DRY и, косвенно, KISS принципа , а также принципа единоличной ответственности .

struct node
{
    int data;
    node* left;
    node* right;

    node(int val) : data(val), left(NULL), right(NULL) {}        
};

class tree
{
private:
    node* root;
public:
    tree();
    tree(int val);

    void insert(int val);
};

tree::tree() : root { NULL }
{
}

tree::tree(int val) : root(new node(val))
{
}

void tree::insert(int val)
{
    if (!root)
    {
        root = new node(val);
    }
    else
    {
        node* t = root;
        node* p = NULL;
        
        while (t)
        {
            p = t;
            
            if (val < t->data)
                t = t->left;
            else
                t = t->right;
        }
        
        t = new node(val);
        
        if (t->data < p->data)
            p->left = t;
        else
            p->right = t;
    }
}

Кроме того, вы также можете сделать insert рекурсивным.

struct node
{
    int data;
    node* left;
    node* right;

    node(int val) : data(val), left(NULL), right(NULL) {}        
};

class tree
{
private:
    node* root;
public:
    tree();
    tree(int val);

    void insert(int val);
protected:
    void insertat(node* p, int val);
};

void tree::insert(int val)
{
    if (!root)
        root = new node(val);
    else
        insertat(root, val);
}

void tree::insertat(node* t, int val);
{
    if (val < t->data)
    {
        if (t->left)
            insertat(t->left, val);
        else
            t->left = new node(val);
    }
    else
    {
        if (t->right)
            insertat(t->right, val);
        else
            t->right = new node(val);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...