I have attempted to write the following method recursively to insert a node into a binary tree. The strategy was to basically insert the node in any NULL left or right pointers.
typedef struct BinaryTreeNode {
int data;
BinaryTreeNode * left;
BinaryTreeNode * right;
} BinaryTreeNode;
void InsertElementInBinaryTree(BinaryTreeNode *root, BinaryTreeNode *element) {
if(root) {
if(root -> left == NULL) root -> left = element;
else if(root -> right == NULL) root -> right = element;
InsertElementInBinaryTree(root -> left, element);
InsertElementInBinaryTree(root -> right, element);
}
}
The method is called as follows in the main function
InsertElementInBinaryTree(&root , new BinaryTreeNode{8, NULL,NULL});
The issue is that this call always returns a segmentation fault error so I believe the error is in the recursion ?
You're missing some conditions:
if (root->data > element->data) {
if (root->left == NULL) {
root->left = element;
} else {
InsertElementInBinaryTree(root->left, element);
}
} else {
if (root->right == NULL) {
root->right = element;
} else {
InsertElementInBinaryTree(root->right, element);
}
}
The function can look the following way
void InsertElementInBinaryTree( BinaryTreeNode * &root, int data )
{
if ( root == nullptr )
{
root = new BinaryTreeNode { data, nullptr, nullptr };
}
else if ( data < root->data )
{
InsertElementInBinaryTree( root->left, data );
}
else
{
InsertElementInBinaryTree( root->right, data );
}
}
and called like
InsertElementInBinaryTree( root , 8 );
and the object root should be defined initially like
BinaryTreeNode *root = nullptr;
If you are trying to implement binary tree then for any current node all the nodes from the left subtree should have lower data than the data in current node and all the data from the right subtree should be greater.
void InsertElementInBinaryTree(BinaryTreeNode *&root, BinaryTreeNode *element) {
if(root == NULL) { root = element; return;}
if(root -> data > element -> data)
InsertElementInBinaryTree(root->left, element);
else
InsertElementInBinaryTree(root->right, element);
}
So actually data values define the position element will inserted at. Also I'm passing BinaryTreeNode *&root as a reference in order the root pointer to be modifiable.
Usage:
// declare root
BinaryTreeNode* root;
// insertion, no & operator before root
InsertElementInBinaryTree(root, new BinaryTreeNode{8, NULL,NULL});
Related
I have been trying to get this function working for the longest time now. It is part of an assignment for an online course, but it seems no matter what I submit, the function fails for both the empty child test and the left child test. See code below. The main() function is deliberately commented out. Any info./input is much appreciated.
// C++ binary trees and stuff;
//
#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
using namespace std;
class BST
{
public:
int data;
BST *left;
BST *right;
//BST *root;
// BST() constructor
BST (int num)
{
data = num;
left = nullptr;
right = nullptr;
root = nullptr;
}
// constructors for root node(s), initializing as root when no values exist yet;
BST() : root (nullptr){}
BST (BST *rootNode) : root(rootNode){}
void insert (int value)
{
BST *newNode = new BST();
newNode = root;
if (root == nullptr)
{
root = new BST (value);
}
else
{
root->data = value;
}
// check if newNode's value equals the passed-in value:
if (value == root->data)
{
//cout << "\nWarning! Value already exists in tree, so nothing will be done.\n";
return;
}
// check if value is < or > newNode's value:
if (value <= root->data)
{
if (root->left == nullptr)
{
// make a new node as the left child of this node,
root->left = new BST(value);
}
else
{
// recursively call insert() on tree's left side,
root->left->insert(value);
}
}
else
{
if (root->right == nullptr)
{
// make a new node as the right child of this node,
root->right = new BST(value);
}
else
{
// recursively call insert() on tree's right side,
root->right->insert(value);
}
}
}
public:
BST *root;
};
/*
int main (int argc, char *argv[])
{
//...insert code here,
// create nodes,...
BST rootNode(5);
BST leftNode(4);
BST rightNode(6);
// connect the nodes to the tree via rootNode.left and rootNode.right,..
rootNode.left = &leftNode;
rootNode.right = &rightNode;
printf ("\nData (root) value = %i, rootNode.left = %i, and rootNode.right = %i\n",
rootNode.data, rootNode.left->data, rootNode.right->data);
cout << "\n\nHello, Solar System!\n";
return 0;
}
*/
Okay, here's my suggestion. You need to reformat your code. You need two classes. You need a BST, and you need a Node. The various methods to add/remove/traverse are part of the BST class. Nodes are just Nodes.
So:
class BST_Node {
public:
int value;
BST_Node * left = nullptr;
BST_Node * right = nullptr;
// Define constructors, etc.
};
class BST {
public:
BST_Node * root = nullptr;
BST_Node * insert(int value);
void insertNode(BST_Node *node);
void insertNodeBelow(BST_Node *nodeToInsert, BST_Node *startingNode);
};
BST_Node * BST::insert(int value) {
BST_Node * node = new BST_Node(value);
insertNode(node);
return node;
}
void BST::insertNode(BST_Node *node) {
if (node == nullptr) {
return;
}
if (root == nullptr) {
root = node;
}
else {
insertNodeBelow(node, root);
}
}
void BST::insertNodeBelow(BST_Node *node, BST_Node *startingNode) {
if (node == nullptr || startingNode == nullptr) {
return;
}
if (node->value < startingNode->value) {
if (startingNode->left != nullptr) {
insertNodeBelow(node, startingNode->left);
}
else {
startingNode->left = node;
}
}
else {
if (startingNode->right != nullptr) {
insertNodeBelow(node, startingNode->right);
}
else {
startingNode->right = node;
}
}
}
How this works... First, the logic of how to store nodes is in BST. Nodes don't care. Second, I made methods for either inserting a value or a node. Because I think that's handy. That should be fairly easy to understand.
The root node can be null, if so, then your inserted node is now root. Otherwise it calls the recursive insertion function. Now, you could simplify this a little, but I didn't want to get too clever.
So it's simple. We look to see where it belongs relative to the point we're at (initially the root). Either we go into the left branch or the right branch. But that branch could be empty, so you just plop it right in. If it's not empty, then you recurse.
I didn't test it.
I'm learning binary trees and want to implement with OOP where I have a struct Node and create a BST Object. I'm trying to create an insert function with this approach and am running into the issue where I can't recursively traverse the tree to add a new node - that is, unless I overload the method, essentially copying it, to call the new method with a pointer to left or right. Hard to explain, but right now I have two methods, and I'm not sure if I'm missing something obvious to just have 1 method with 1 parameter int data, or if this approach just isn't correct. I feel like there's something valuable for me to learn here. Many thanks.
#include <iostream>
struct Node
{
Node *right;
Node *left;
int data;
};
class BST
{
public:
Node* root;
public:
BST()
:root(NULL)
{
}
//inserts node taking parameter data
Node* insertNode(int data)
{
//if tree is empty, create root
if (root == NULL)
{
root = newNode(data);
}
//if data is smaller than or equal to root, insert left
else if (data <= root->data)
{
root->left = insertNode(root->left, data);
}
//data is larger than root, insert right
else
{
root->right = insertNode(root->right, data);
}
return root;
}
//inserts new node
Node* insertNode(Node *root, int data)
{
//if tree is empty, create root
if (root == NULL)
{
root = newNode(data);
}
//if data is smaller than or equal to root, insert left
else if (data <= root->data)
{
root->left = insertNode(root->left, data);
}
//data is larger than root, insert right
else
{
root->right = insertNode(root->right, data);
}
return root;
}
Node* newNode(int data)
{
Node *temp = new Node;
temp->data = data;
temp->left = NULL;
temp->right = NULL;
return temp;
}
};
int main() {
BST bst1;
bst1.insertNode(30);
bst1.insertNode(15);
return 0;
}
You can save the redundancy by having one call forward to the other:
Node* insertNode(int data)
{
return insertNode(root, data);
}
Note that having identical names for your class member (Node* root) and the local variable in Node* insertNode(Node *root, int data) is error-prone.
Also please do not forget to delete what you new.
This class's purpose is to emulate the functions of a Binary Search Tree. In the below code, I am trying to adapt it from a struct and a bunch of functions, into a wrapper class, called BST. One thing I am not sure of however, is how to access 'root' from within the node struct. Root is currently declared within the BST class.
class bst
{
public:
struct Node
{
public:
int data;
struct Node *left;
struct Node *right;
Node* FindMin(Node* root)
{
while(root->left != NULL) root = root->left;
return root;
}
Node* Insert(Node *root,int data)
{
if(root == NULL) {
root = new Node();
root->data = data;
root->left = root->right = NULL;
//Update Height & Size
bstHeight = 0;
bstSize = 0;
}
else if(data <= root->data)
root->left = Insert(root->left,data);
else
root->right = Insert(root->right,data);
return root;
}
Node* Delete(struct Node *root, int data)
{
if(root == NULL) return root;
else if(data < root->data) root->left = Delete(root->left,data);
else if (data > root->data) root->right = Delete(root->right,data);
//Value found
else {
// Case 1: No child
if(root->left == NULL && root->right == NULL)
{
delete root;
root = NULL;
//Update Height & Size
bstHeight = 0;
bstSize = 0;
}
//Case 2: One child
else if(root->left == NULL)
{
struct Node *temp = root;
root = root->right;
delete temp;
//Update Height & Size
bstHeight = 0;
bstSize = 0;
}
else if(root->right == NULL)
{
struct Node *temp = root;
root = root->left;
delete temp;
//Update Height & Size
bstHeight = 0;
bstSize = 0;
}
// case 3: 2 children
else
{
struct Node *temp = FindMin(root->right);
root->data = temp->data;
root->right = Delete(root->right,temp->data);
//Update Height & Size
bstHeight = 0;
bstSize = 0;
}
}
return root;
}
//# of Nodes in tree
void size(Node *root)
{
//Check if end
if(root == NULL) return;
//Not end
else
{
bstSize = bstSize + 1;
size(root->left); //Visit left subtree
size(root->right); // Visit right subtree
}
}
void height(Node *root, int temp)
{
//Check if end
if(root == NULL)
{
if(temp > bstHeight)
{
bstHeight = temp;
}
return;
}
//Not end
else
{
temp = temp + 1;
height(root->left, temp); //Visit left subtree
height(root->right, temp); // Visit right subtree
}
}
//Function to visit nodes in Inorder
void show()
{
if(root == NULL) return;
show(root->left); //Visit left subtree
printf("%d ",root->data); //Print data
show(root->right); // Visit right subtree
}
void check(Node *root)
{
//End of a 'branch'
if(root == NULL) return;
int value = 0;
value = root->data;
//Checking left subtree
if(value < root->left->data)
{
//Tree is NOT valid
valid = 0;
}
//Checking right subtree
if(value > root->right->data)
{
//Tree is NOT valid
valid = 0;
}
check(root->left); //Visit left subtree
printf("%d ",root->data); //Print data
//check(root->right); // Visit right subtree
}
};
Node* root = NULL;
};
Specifically, in the show function. It's not as simple as putting it into Node with the rest of the functions, as root needs to be unique, and new Node is called at least once. Show will not compile in the current state, and I'm not sure where to proceed from here.
Though the comment says everything, let me give an additional hint:
When you want to keep your code as similar as possible to what you have now, try to add a constructor to the Node class that expects a pointer or reference (preferable) to the root and check, that each time you create a Node, you give the root to the constructor.
By the way, it might even be a better approach to look at some simple Node-based data structure implementations in C++, for example in the thread
Simple linked list in C++
I need to add an item to a binary tree given only the item to be added.
Here is the code I'm given:
void BinaryTree::add(Data * data) {
if (root == NULL) {
root = new BinaryTreeNode(data);
}
else {
root->add(data);
}
}
where root is a private variable of a BinaryTree defined as a BinaryTreeNode.
I need to implement a method:
void BinaryTreeNode::add(Data * data);
where a BinaryTreeNode is:
class BinaryTreeNode {
public:
Data * nodeData;
BinaryTreeNode * left;
BinaryTreeNode * right;
/**
* Constructor
*/
BinaryTreeNode(
Data * data,
BinaryTreeNode * left = NULL,
BinaryTreeNode *right = NULL
)
: nodeData(data), left(left), right(right)
{ }
// ...
I want to do this recursively, but I'm not positive how when you're only passed the data to be added.
My idea that doesn't work is:
void BinaryTreeNode::add(Data * newData) {
BinaryTreeNode * temp = this;
if (temp == NULL) {
temp->nodeData = newData;
} else {
if (newData->compareTo(nodeData) < 0) {
temp->left->add(newData);
} else {
temp->right->add(newData);
}
}
}
You are setting temp to this and then comparing it to NULL. this should never be NULL. You need to check if the left and right are NULL.
Well a binary tree, atleast how I know how to implement involves something like the following with two objects, one containing the the treenode object, and the other acting as an interface for the whole tree.
class cBinaryTree {
public:
bool insert(int inData);
//Other operations
private:
cBinaryTreeNode* root;
bool leftInsertion;
cBinaryTreeNode* getRoot() { return root; }
As you are comparing the actually value of the input data and placing it accordingly, this qualifies as a binary search tree. Then the insertion function can be written as
bool cBinaryTree::insert(int inData) {
//handle case if its first node.
cBinaryTreeNode *Parent = getInsertionNodePosition(getRoot(), inData);
cBinaryTreeNode *newNode = createNewNode(inData);
if(leftInsertion) //insert into left. add return statement
Parent->setLeftChild() = newNode;
else //insert into right
}
The recursive lookup function will be something like
cBinaryTreeNode* getInsertionNodePosition(cBinaryTreeNode* node,int inData) {
//Check left subtree and proceed from there.
if(inData < node->getData()) {
if(node->getLeftChild() == NULL) {
leftInsertion = true;
return node;
}
else {
node = node->getLeftChild();
return getInsertionNodePosition(node, inData);
}
}
//Similarly Check right subtree.
Hope this helps.
I'm trying to make a BST and need to print it inorder, postorder, and preorder.
The thing am not sure about is how to create this tree in my main() function.
struct Tree_Node
{
Tree_Node *right;
Tree_Node *left;
int info;
};
class bTree
{
private:
Tree_Node *root;
public:
bTree();
void bTree::Insert(Tree_Node*& tree, int item);
void bTree::preorderPrint(Tree_Node *root);
};
bTree::bTree()
{
root = NULL;
}
void bTree::Insert(Tree_Node*& tree, int item)
{
if (tree == NULL)
{
tree = new Tree_Node;
tree->right = NULL;
tree->left = NULL;
tree->info = item;
}
else if (item < tree->info)
Insert(tree->left, item);
else
Insert(tree->right, item);
}
void bTree::preorderPrint(Tree_Node *root)
{
if ( root != NULL )
{
cout << root->info << " ";
preorderPrint( root->left );
preorderPrint( root->right );
}
}
void main()
{
// This is where I need help at
// I'm not sure how to insert a new node
bTree Test;
Test.Insert(
}
By the looks of things, you can just write
Test.Insert(Test.root, 3); // Insert 3
Test.Insert(Test.root, 4); // Insert 4
and that should work. Of course, you'll have to make root public.
However, this is a bit awkward, since the first parameter will always be bTree.root - and you don't need to make that public. Remember that the user of your data type (you or anyone else) shouldn't have to care about internals such as nodes - they only care about their data. Instead, I'd recommend making a convenience Insert method which only needs to take an integer (not a tree node) - this is called Overloading.
void bTree::Insert(int item)
{
Insert(root, item);
}
// Keep the other insert method, but make it private.
Then you can just write:
Test.Insert(3);
Test.Insert(4);
void bTree::Insert(int item)
{
Tree_Node * node = new Tree_Node;
node->left = NULL;
node->right = NULL;
node->info = item;
if (root == NULL)
{
root = node;
return;
}
Tree_Node * t = root;
Tree_Node * p = root;
while(1)
{
if (item < t->info)
{
t = t->left;
if(t == NULL)
{
p->left = node;
return;
}
}
else if(item > t->info)
{
t = t->right;
if(t == NULL)
{
p->right = node;
return;
}
}
else //item already exists in the tree
return;
p = t;
}
}
//now you can insert nodes like
Test.Insert(5);
Test.Insert(6);