I was trying to use to insert into a binary tree using while loop. However it seems to have a bug: it only takes the first number and doesn't take the rest. I don't know where I made the mistake.
I've created the following code:
void BTC::Insert(int Data)
{Node *newNode = new Node;
if (head == 0)
{
head = node;
}
else
{
Node* ptr = head;
if(ptr->childs>2)
{
if (Data > ptr->data)
{
ptr->right = node;
}
else if (Data <= ptr->data)
{
ptr->left = node;
}
ptr->childs++;
}
else
{
While(ptr->childs==2)
{
if (Data > ptr->data)
{
ptr = ptr->right;
}
else if (Data <= ptr->data)
{
ptr = ptr->left;
}
}
}
}
class Node
{
public:
int data;
Node* right;
Node* left;
int childs;
Node() : right(0), left(0)
{}
Node(int data) : data(data), right(0), left(0),childs(0)
{}
}
}
Related
I have written this delete function to delete a node in a binary search tree. The problem is it deletes the root node of the key itself. Tried Debugging but not clear whats wrong with it.
Also I don't understand why are we setting this node->m_left=deletenode(data,node->m_left);
#include "node.h"
#include <queue>
template<class T>
class bst
{
private:
Node<T>* root;
public:
bst()
{
root = nullptr;
}
~bst()
{
deletree(root);
}
Node<T>* gethead()
{
return this->root;
}
void addnode(Node<T>* node, T data)
{
if (this->root == nullptr) {
Node<T>* new_node = new Node<T>(data);
this->root = new_node;
}
else if (data > node->m_data) {
if (node->m_right != nullptr) {
addnode(node->m_right, data);
}
else {
Node<T>* new_node = new Node<T>(data);
node->m_right = new_node;
}
}
else if (data < node->m_data) {
if (node->m_left != nullptr) {
addnode(node->m_left, data);
}
else {
Node<T>* new_node = new Node<T>(data);
node->m_left = new_node;
}
}
}
void addnode(T data)
{
addnode(this->root, data);
}
Node<T>* deletenode(T data, Node<T>* node)
{
//base case
if (node == nullptr) {
return nullptr;
}
if (data < node->m_data) {
node->m_left = deletenode(data, node->m_left);
}
if (data > node->m_data) {
node->m_right = deletenode(data, node->m_right);
}
if (node->m_left == nullptr && node->m_right == nullptr) {
node = nullptr;
}
return nullptr;
}
};
I'm trying to implement the insertion function used on geeksforgeeks.com but am running into some problems trying to work it into my current code.
I have a vector with the data I need to put into the binary tree. I use this function to pass the numbers into the insertion function:
void populateTree(vector<string> dataVec) {
for (int i = 0; i < dataVec.size(); i++) {
insert(stoi(dataVec[i]), root);
}
}
This is the insertion function:
node* insert(int x, node* node) {
if (node == nullptr)
return newNode(x);
if (x < node->data)
node->left = insert(x, node->left);
else
node->right = insert(x, node->right);
return root;
}
New node function:
node* newNode(int num) {
node* temp = new node;
temp->data = num;
temp->left = temp->right = nullptr;
temp->level = 1;
return temp;
}
Root is a private member within the class which is initialized to nullptr. I'm not sure how I should go about making the first node that comes in from the vector as the root and then keep inserting things beginning from there recursively. Thanks!
The problem in your is related to use of pointer.
Instead of using node* insert(int x, node* node) you should use node* insert(int x, node** node) or node* insert(int x, node*& node) and adopt your code accordingly.
Following is corrected sample code. See it in execution here:
#include <iostream>
#include <vector>
using namespace std;
struct Node
{
int val;
Node* left;
Node* right;
Node(int v)
{
val = v;
left = right = nullptr;
}
};
class Tree
{
Node* root;
Tree()
{
root = nullptr;
}
public:
static void insert(int x, Node*& node)
{
if (node == nullptr)
{
node = new Node(x);
}
else
{
if (x < node->val)
insert(x, node->left);
else
insert(x, node->right);
}
}
static Tree* populateTree(vector<string> dataVec)
{
Tree* t= new Tree();
for (int i = 0; i < dataVec.size(); i++)
{
insert(stoi(dataVec[i]), t->root);
}
return t;
}
static void printTree(Node* node, string s)
{
if(node == nullptr) return;
cout<<s<< "+"<<node->val <<endl;
s += "----";
printTree(node->left,s);
printTree(node->right, s);
}
static void printTree(Tree* t)
{
if(t)
{
printTree(t->root, "");
}
}
};
int main() {
Tree* t = Tree::populateTree({"70", "2", "7", "20", "41", "28", "20", "51", "91"});
Tree::printTree(t);
return 0;
}
I've an assignment which is to write an index builder application , which takes text consisting of lines and prints a list of the words of the text and the lines they appear on are printed next to them.
but i faced a problem when i tried to handle the case if the word already exist , it's always add a redundant number to the vector
can anyone help me please?
This is the definition of the BSTnode:
class BSTnode
{
public:
string data;
vector<int> linesAppear;
BSTnode* left;
BSTnode* right;
BSTnode()
{
left = right = NULL;
}
};
This is the definition of the BSTFCI:
class BSTFCI
{
public:
BSTnode* root;
BSTFCI()
{
root = NULL;
}
void add(string ToBST,int lineAppear);
BSTnode* Insert(BSTnode*& node,string ToBST,int lineAppear);
BSTnode* create_new_node(string ToBST,int lineAppear);
};
The functions for insert
BSTnode* BSTFCI::create_new_node(string ToBST,int lineAppear)
{
BSTnode* Temp = new BSTnode();
Temp->data = ToBST;
Temp->left = Temp->right = NULL;
Temp->linesAppear.push_back(lineAppear);
return Temp;
}
BSTnode* BSTFCI::Insert(BSTnode*& node,string ToBST,int lineAppear)
{
if(node == NULL)
{
node = create_new_node(ToBST,lineAppear);
}
if(ToBST > node->data)
{
node->right = Insert(node->right,ToBST,lineAppear);
}
if(ToBST < node->data)
{
node->left = Insert(node->left,ToBST,lineAppear);
}
//cout <<"inside insert"<< ToBST << endl;
if(node->data == ToBST)
{
node->linesAppear.push_back(lineAppear);
// cout <<"inside insert condition "<< node->data << endl;
}
return node;
}
void BSTFCI::add(string ToBST,int lineAppear)
{
root = Insert(root,ToBST,lineAppear);
}
the main function:
int main()
{
BSTFCI o;
string input,ToBST;
int lineAppear = 0;
while(getline(cin,input))
{
if(input == "done")
{
break;
}
lineAppear++;
istringstream convert(input);
while(convert >> ToBST)
{
o.add(ToBST,lineAppear);
}
}
o.print_inOrder(o.root);
return 0;
}
It's because you add the number both in create_new_node (which should be a constructor in BSTnode, really) and later, when if(node->data == ToBST).
You need to decide whether to add it when creating a node or afterwards, but doing it on creation makes the most sense – why would you add a node without also giving it an occurrence?
I would do like this:
class BSTnode
{
public:
string data;
vector<int> linesAppear;
BSTnode* left;
BSTnode* right;
BSTnode() : left(nullptr), right(nullptr) {}
BSTnode(const std::string& word, int appearance)
: data(word),
linesAppear(1, appearance),
left(nullptr),
right(nullptr)
{
}
};
BSTnode* BSTFCI::Insert(BSTnode* node, string ToBST,int lineAppear)
{
if(node == nullptr)
{
return new BSTnode(ToBST, lineAppear);
}
if(ToBST > node->data)
{
node->right = Insert(node->right, ToBST, lineAppear);
}
else if(ToBST < node->data)
{
node->left = Insert(node->left, ToBST, lineAppear);
}
else
{
node->linesAppear.push_back(lineAppear);
}
return node;
}
Note that there is no point in both passing node by reference and returning it, so I kept the returning and removed the reference.
You could also do the opposite.
I am trying to understand BSTs and how to insert elements into it iteratively. My node structure implementation looks like so:
struct Node{
Node *left;
Node *right;
T data; //template class
};
And my insertion implementation looks like so:
template<typename T>
bool BST<T>::Insert(const T value)
{
Node *newNode = new Node;
newNode -> data = value;
newNode -> left = NULL;
newNode -> right = NULL;
if(root == NULL) {root = newNode;} //If the BST is empty
else
{//The BST is not empty
Node *ptr = root; //points to the current Node
Node *ptr_parent; //points to the parent Node
while(ptr != NULL)
{
if((ptr -> data) > value)
{
ptr_parent = ptr;
ptr = ptr -> left;
}
if((ptr -> data) < value)
{
ptr_parent = ptr;
ptr = ptr -> right;
}
}
}
ptr = newNode; //insert the newNode at the spot
if((ptr_parent -> data) < value)
ptr_parent -> right = newNode;
else
ptr_parent -> left = newNode;
return true;
}
The insertion works when adding the first Node into an empty tree but I get a segmentation fault whenever i try to add more Nodes. I understand that there are posts that show how to implement insertions into BSTs but most of them show the recursive method, and those with iterative examples are incomplete or too specific. Thank you.
I think I'd do things a little differently. First, I'd simplify the other code a little by adding a ctor to the Node class:
struct Node{
Node *left;
Node *right;
T data;
Node(T const &data) : left(nullptr), right(nullptr), data(data) {}
};
Then you can use a pointer to a pointer to traverse the tree and insert the item:
bool insert(const T value) {
Node **pos;
for (pos = &root; *pos != nullptr;) {
if (value < (*pos)->value)
pos = &(*pos)->left;
else if ((*pos)->value < value )
pos = &(*pos)->right;
else
return false;
}
*pos = new Node(value);
return true;
}
Note that I've delayed creating the new node until after we've dropped out of the loop. This way, if we have a duplicate element, we can just return (without leaking a node, since we haven't allocated a new node yet).
For what it's worth, if you were going to do this recursively, it would probably be easier to use a reference to a pointer instead of a pointer to a pointer.
I was able to make my original code work last night, I'm sharing the answer here:
template<typename T>
bool BST<T>::Insert(const T value)
{
Node *ptr;
Node *ptr_parent;
if(root == NULL)
{//The BST is Empty...
Node *newNode = new Node;
newNode -> data = value;
newNode -> left = NULL;
newNode -> right = NULL;
root = newNode;
ptr = root;
} else { //traversing the tree to find the insertion point
ptr = root;
while(ptr != NULL)
{
if((ptr -> data) == value) {return false;} //to check for duplicates
if(value < (ptr -> data))
{
ptr_parent = ptr;
ptr = ptr -> left;
} else {
ptr_parent = ptr;
ptr = ptr -> right;
}
}
Node *newNode = new Node;
newNode -> data = value;
newNode -> left = NULL;
newNode -> right = NULL;
//checking for parent value to determine if
//the Node is a left or right child
if(value < (ptr_parent -> data))
ptr_parent -> left = newNode;
else
ptr_parent -> right = newNode;
}
++count;//to keep track of the Node count
return true;
}
For my own sake I wanted to solve this without using double pointers.
You didn't handle the case when ptr->data == value so the loop will be infinite whenever a duplicate is found, and ptr = newNode doesn't do anything, it just makes ptr point to newNode. Try this
//ptr holds the address of pointers to nodes.
Node **ptr = &root;
while(*ptr != NULL){
if((*ptr)->data > T)
ptr = &(*ptr)->right;
else
ptr = &(*ptr)->left;
//Not handling duplicates
}
//Change the value of the pointer to newNode
*ptr = newNode;
Use hard pointers
Node **ptr = &root; //points to the current Node
Node **ptr_parent; //points to the parent Node
When you are trying to do this
ptr = newNode; //insert the newNode at the spot
it doesn't do anyithing because you need to modify the pointer which points to the left or the right subnode
something like this:
template<typename T>
bool BST<T>::Insert(const T value)
{
Node *newNode = new Node;
newNode -> data = value;
newNode -> left = NULL;
newNode -> right = NULL;
if(root == NULL) {root = newNode;} //If the BST is empty
else
{//The BST is not empty
Node **ptr = &root; //points to the current Node
Node **ptr_parent; //points to the parent Node
while((*ptr) != NULL)
{
if(((*ptr) -> data) > value)
{
ptr_parent = ptr;
ptr = &ptr -> left;
}
if(((*ptr) -> data) < value)
{
ptr_parent = ptr;
ptr = &ptr -> right;
}
}
}
(*ptr) = newNode; //insert the newNode at the spot
if(((*ptr_parent) -> data) < value)
(*ptr_parent) -> right = newNode;
else
(*ptr_parent) -> left = newNode;
return true;
}
As I understand, it is failing because of following line:
ptr = newNode; //insert the newNode at the spot
after the while loop your ptr is NULL otherwise you can not exit from the while loop. You are assigning a struct to NULL, which is not right.
Hopefully this helps. Everything else looks normal.
void insert(node* root, int value)
{
if (root == NULL)
{
root = new node;
root->data = value;
return;
}
while(!((root->data < value && root->right == NULL) || (root->data >= value && root->left == NULL)))
{
if (root->data < value)
root = root->right;
else
root = root->left;
}
if (root->data < value)
{
root->right = new node;
root->right->data = value;
} else
{
root->left = new node;
root->left->data = value;
}
}
template <class T>
class TreeNode{
private:
T data;
TreeNode<T>* right,*left;
public:
void setData(T d){
this->data =d;
}
T getData(){
return this->data;
}
void setRight(TreeNode<T>* r){
this->right =r;
}
TreeNode<T>* getRight(){
return this->right;
}
void setLeft(TreeNode<T>* r){
this->left =r;
}
TreeNode<T>* getLeft(){
return this->left;
}
static TreeNode<T>* newNode(T data){
TreeNode<T>* n = new TreeNode<T>();
n->setData(data);
n->setRight(NULL);
n->setLeft(NULL);
return n;
}
};
template <class T>
class BinaryTree{
private:
TreeNode<T>* root;
public:
void insert(T data){
TreeNode<T>* n = TreeNode<T>::newNode(data);
if(root==NULL)
root = n;
else{
TreeNode<T>* t = root;
while(t!=NULL){
if(n->getData() >= t->getData()){
if(t->getRight()==NULL){
t->setRight(n); //newnode attached as right child in tree
t = NULL;
}
else
t = t->getRight();
}
else{
if(t->getLeft()==NULL){
t->setLeft(n); //newnode attached as left child in tree
t=NULL;
}
else
t = t->getLeft();
}
}
}
}
void preorder(){
TreeNode<T>* t = root;
preorderUtil(t);
}
void preorderUtil(TreeNode<T>* node){
if(node==NULL)
return;
preorderUtil(node->getLeft());
cout<<node->getData()<<" ";
preorderUtil(node->getRight());
}
};
I answered a case here Binary Search Tree insertion doesn't work see if it helps
void insert(int val)
{
Node *newNode;
newNode=new Node;
newNode->data=val;
Node *currentNode=root;
Node *parentNode;
if(root==NULL)
{
newNode->left=NULL;
newNode->right=NULL;
}
else
{
while(currentNode!=NULL)
{
if((currentNode->data)>val)
{
parentNode=currentNode;
currentNode=currentNode->left;
}
if((currentNode->data)<val)
{
parentNode=currentNode;
currentNode=currentNode->right;
}
}
}
currentNode=newNode;
if((parentNode->data)<val)
{
parentNode->right=newNode;
}
else
{
parentNode->right=newNode;
}
}
I wrote a function to insert nodes into a binary search tree. However, when trying to build a solution in Visual Studio 2013, I receive this: "Unhandled exception at 0x00FD4CD0 in BST.exe: 0xC0000005: Access violation reading location 0xCCCCCCCC." The following is my code.
void BST::insert(int value) {
Node* temp = new Node();
temp->data = value;
if(root == NULL) {
root = temp;
return;
}
Node* current;
current = root;
Node* parent;
parent = root;
current = (temp->data < current->data) ? (current->leftChild) : (current->rightChild);
while(current != NULL) {
parent = current;
current = (temp->data < current->data) ? (current->leftChild) : (current->rightChild);
}
if(temp->data < parent->data) {
parent->leftChild = temp;
}
if(temp->data > parent->data) {
parent->rightChild = temp;
}
}
Then in my main function I have:
int main() {
BST bst;
bst.insert(10);
system("pause");
}
When I remove bst.insert(10); in my main function, I no longer receive the unhandled exception.
The following is the initialization of my struct
struct Node {
int data;
Node* leftChild;
Node* rightChild;
Node() : leftChild(NULL), rightChild(NULL) {}
};
struct BST {
Node* root;
void insert(int value);
BST() : root(NULL) {}
};
In your insertion function you are not setting leftChild and rightChild to NULL.
void BST::insert(int value) {
Node* temp = new Node();
temp->data = value;
temp->leftChild = NULL;
temp->rightChild = NULL;
if(root == NULL) {
root = temp;
return;
}
Also, I cannot be sure (as you have not posted the constructor for BST) but you may not have set root to NULL in the BST constructor. Try with these modifications.
Seems like you do not have a constructor in BST from what you have posted:
struct BST {
Node* root;
void insert(int value);
BST(): root(NULL) { } // add a constructor to initialize root to NULL
};