Правильный способ использования указателей на функции для обхода BST - PullRequest
0 голосов
/ 21 мая 2019

Я создаю класс шаблона двоичного дерева поиска и хочу использовать указатели функций для функции обхода inorder, я в порядке с указателями на функции, но по какой-то причине теряюсь в том, как использовать inorder, как только код будет на месте.не так много других вещей в Интернете помогли мне, поэтому любая обратная связь была бы отличной.

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 ();недостаточно аргументов

Ответы [ 2 ]

2 голосов
/ 21 мая 2019

Допустим, вы хотите напечатать значение каждого узла в дереве:

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 и лямбда-выражениях . См. Также этот ответ.

2 голосов
/ 21 мая 2019

Вам нужно потратить недели, чтобы больше узнать о 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 ++ , такую ​​как Программирование - Принципы и практика использования C ++ (разработчик C ++). Затем загляните на какой-нибудь C ++ справочный сайт. Читайте также как отлаживать небольшие программы (очень актуально здесь).

Затем скомпилировать все предупреждения и отладочную информацию . Если ваш компилятор GCC , скомпилируйте как минимум с g++ -Wall -g. Вы получите хорошее диагностическое сообщение. Покажите это в вашем вопросе, пожалуйста .

Наконец, вы объявили свой inorder как принимающий один аргумент, и вы не даете ни одного при вызове этого (и при этом вы не согласны):

   tree.inorder();
   //           ^     missing argument

Вы ошибочно спросили:

Я создаю класс шаблона двоичного дерева поиска и хочу использовать указатели на функции

Как я уже говорил, вам следует избегать указателей на функции (они так похожи на C, а не на подлинный C ++) и использовать некоторые std::function type в объявление этого inorder и передать, возможно, некоторое анонимное лямбда-выражение на сайте вызова . Потому что то, что вы должны передать концептуально, это не указатель на функцию, а замыкание (которое объединяет необработанный указатель функции с данными, закрытые значения) или, если вы, к сожалению, хотите избежать подлинный C ++ и совместимость с простым C процедурным программированием * стиль 1071 * и соглашения о вызовах , имеют обратные вызовы , поэтому передают не только необработанный указатель на функцию, но и некоторые данные клиента.

Итак, вы действительно хотите объявить и определить (как большинство C ++ контейнеров do)

template<class T>
inline void Bst<T>::inorder(std::function<void(T&)> fun) const;

(позже, как оптимизация , вы можете передать fun как const reference ) и использовать его (с лямбда-выражением), как, например, :

tree.inorder([](T& x) { std::cout << x << std::endl; });

Я утверждаю, что ваш учитель должен сначала научить вас замыканиям и тому, как их красиво использовать в каком-то стиле функционального программирования (что вполне естественно в вашем случае), а затем объяснить их реализацию 1095 * также и позже, обучая указателям на функции. В большинстве случаев указатели функций устарели в C ++ (но они существуют для совместимости с C и устаревшими версиями C ++).

PS. То, что вы не понимаете, занимает несколько десятков страниц для объяснения (поскольку система типов C ++ очень сложна). У нас не так много места здесь (и времени, чтобы написать это). Пожалуйста, уделите неделю чтению хорошей книги по C ++ .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...