#c #binary-search-tree
#c #двоичное дерево поиска
Вопрос:
Я попытался создать двоичное дерево поиска, используя youtube и примеры от моего профессора, чтобы помочь, но отобразить в Driver.cpp не показывает ни одного узла дерева, кроме «null» (который должен был представлять nullptr). Я думаю, это потому, что мой «root» остается как nullptr, хотя я вставил новый узел. Вывод должен быть «23 null null». Извините, если коды не короткие и не оптимизированы, я хочу прояснить ситуацию для себя, когда я перечитаю их позже.
PS: я удалил некоторые незавершенные функции в коде, размещенном здесь, поэтому могут быть незначительные ошибки
//Driver.cpp
#include <iostream>
#include "Overall Tree.h";
using namespace std;
int main()
{
BinaryTree tree_1;
tree_1.insertNode(23);
tree_1.display();
return 0;
}
//Overall Tree.h
#include <iostream>
using namespace std;
class BinaryTree
{
struct Node
{
int data;
Node* left;
Node* right;
};
private:
Node* root;
public:
// Constructors and Destructors
BinaryTree();
//traversal functions
void preOrder();
void inOrder();
void postOrder();
void preOrderTraverse(Node*);
void inOrderTraverse(Node*);
void postOrderTraverse(Node*);
//display function
void display();
//insert functions
void insertNode(int);
void insert(Node*, Node*);
};
BinaryTree::BinaryTree()
{
root = nullptr;
}
//display traversals
void BinaryTree::display()
{
cout << "Pre-order traversal: " << endl;
preOrder();
cout << endl << endl;
cout << "In-order traversal: " << endl;
inOrder();
cout << endl << endl;
cout << "Post-order traversal: " << endl;
postOrder();
}
// traversals
void BinaryTree::preOrder()
{
preOrderTraverse(root);
}
void BinaryTree::inOrder()
{
inOrderTraverse(root);
}
void BinaryTree::postOrder()
{
postOrderTraverse(root);
}
void BinaryTree::preOrderTraverse(Node* root)
{
if (root != nullptr)
{
cout << root->data << " ";
preOrderTraverse(root->left);
preOrderTraverse(root->right);
}
else
cout << "null ";
}
void BinaryTree::inOrderTraverse(Node* root)
{
if (root != nullptr)
{
preOrderTraverse(root->left);
cout << root->data << " ";
preOrderTraverse(root->right);
}
else
cout << "null ";
}
void BinaryTree::postOrderTraverse(Node* root)
{
if (root != nullptr)
{
preOrderTraverse(root->left);
preOrderTraverse(root->right);
cout << root->data << " ";
}
else
cout << "null ";
}
//insert
void BinaryTree::insertNode(int x)
{
Node* newNode = new Node;
newNode->data = x;
newNode->left = nullptr;
newNode->right = nullptr;
insert(newNode, this->root);
}
void BinaryTree::insert(Node* newNode, Node* p)
{
if (p == nullptr)
p = newNode;
else
if (newNode->data < p->data)
insert(newNode, p->left);
else if (newNode->data > p->data)
insert(newNode, p->right);
else
cout << "Value already existed in the tree.";
}
Ответ №1:
Вы должны передать указатель на указатель на корень в вашей insert
функции, например:
void BinaryTree::insert(Node* newNode, Node** p)
{
if (*p == nullptr) {
*p = newNode;
} else {
if (newNode->data < (*p)->data) {
insert(newNode, amp;(*p)->left);
} else if (newNode->data > (*p)->data) {
insert(newNode, amp;(*p)->right);
} else {
cout << "Value already existed in the tree.";
}
}
}
а затем используйте эту функцию, например:
insert(newNode, amp;this->root);
Почему указатель на указатель?
Потому что вы хотите, чтобы изменения параметра (в данном случае p
параметра), сделанные в insert
функции, повлияли на аргумент, переданный вызывающим.
Редактировать
Вы также можете использовать reference для этой цели:
void BinaryTree::insert(Node* newNode, Node*amp; p)
{
if (p == nullptr) {
p = newNode;
} else {
if (newNode->data < p->data) {
insert(newNode, p->left);
} else if (newNode->data > p->data) {
insert(newNode, p->right);
} else {
cout << "Value already existed in the tree.";
}
}
}
а затем использовать его как:
insert(newNode, this->root);
Я бы предложил использовать reference из-за более чистого синтаксиса IMO.
Комментарии:
1. спасибо за помощь. Необходимо ли обычно использовать указатель на указатель? Я никогда этого не делал, и обычные аргументы указателя отлично работали в моих прошлых кодах.
2. @SalSo если вы хотите изменить содержимое, вам нужно будет использовать указатель на указатель. Однако, если вам просто нужно отобразить содержимое, тогда будет работать обычный указатель