C++ Binary Tree Programming new Nodes leaving Scope issue - c++

I am a java programmer teaching myself C++.
While writing a binary tree I found that my program did not "add" values to the tree.
#include "stdafx.h"
#include <cstdlib>
#include <iostream>
using namespace std;
class BinaryTree {
struct Node {
public:
int val;
Node* left;
Node* right;
Node::Node(int v) {
val = v;
left = nullptr;
right = nullptr;
}
};
public:
BinaryTree() {
root = nullptr;
}
int size = 0;
int length();
bool BinaryTree::add(int v);
void printTree();
private:
void printTree(Node* n);
Node* root;
};
bool BinaryTree::add(int v) {
if (root == nullptr) {
root = new Node(v);
++size;
return true;
}
Node* ref = root;
cout << ref->val;
while (ref != nullptr) {
if (v < ref->val) {
ref = ref->left;
}
else if (v > ref->val) {
ref = ref->right;
}
else if (v == ref->val) {
return false;
}
}
Node *newNode = new Node(v);
ref = newNode;
++size;
return true;
}
void BinaryTree::printTree() {
printTree(root);
}
void BinaryTree::printTree(Node* n) {
if (n == nullptr) {
return;
}
printTree(n->left);
cout << n->val << endl;
printTree(n->right);
}
int BinaryTree::length() {
return size;
}
void main(int i) {
BinaryTree tree = BinaryTree();
tree.add(6);
tree.add(3);
tree.add(5);
tree.add(7);
tree.add(1);
tree.add(0);
tree.add(0);
tree.printTree();
cout << "binary tree sz is " << tree.length() << endl;
while (true) {};
}
I have been unable to find the problem in regards to why the tree doesn't commit new Nodes except the root.
I used "new" in the code when writing (ref = new Node) etc in the adds method because this should prevent the new Node from being destroyed once it leaves the scope.
If anyone can enlighten me on this issue I will be greatly thankful.

To add a node to the tree you have to link it to some existing node, as in
existing_node->{left or right} = new_node;
Once ref becomes nullptr, you don't have a valid existing node anymore, and it is too late to do anything. Instead, traverse the tree as long as ref->{left or right} is valid:
if (v < ref->val) {
if (ref->left) {
ref = ref->left;
} else {
ref->left = newNode;
return true;
}
}
// etc for v > ref->val

Related

How do I traverse a tree in-order and just get one value at a time instead of all values in C++

I'm trying to traverse a binary tree inorder and the problem I'm trying to solve requires me to return one value at a time. The problem with binary tree traversal is that you get everything at once using recursion.Don't get me wrong, I want everything but not at once.
What I tried implementing an array to store every value and then loop through and get each value.
But this too does not seem to work, CPP is complaining that "undefined reference to `IPAddressAnalyzer::nodesArray'"
Here's a snippet of my code:
struct node
{
int address;
int count;
node* left;
node* right;
};
class IPAddressAnalyzer{
private:
node* root;
static node *nodesArray;
int arrayIndex = 0;
void destroy_tree(node *leaf);
void insert(int ip, int count, node *leaf);
void inorder_print(node *leaf);
And here's where I'm trying to use the array:
void IPAddressAnalyzer::inorder_print(node* leaf)
{
if(leaf != NULL)
{
inorder_print(leaf->right);
nodesArray[arrayIndex].address = leaf->address;
nodesArray[arrayIndex].count = leaf->count;
updateArrayIndex();
inorder_print(leaf->left);
}
}
Here's where I create the array, access the elements in the array and try to write to a file.
//Create the array
tree->createArray(intCounter);
tree->inorder_print();
//Traverse tree and write to a file
int rank =1;
int counter = 0;
int valueHolder = 0;
int nodeIndex = 0;
while (rank<=n){
node element = nodesArray[nodeIndex];
printf("Popped ip: %s count: %d\n", IPAddressToString(element.address), element.count);
if(counter == 0) {
fprintf(outFileStream, "%d, %s, %d\n", rank, IPAddressToString(element.address), element.count);
valueHolder = element.count;
counter++;
}
else if(element.count == valueHolder)
{
fprintf(outFileStream, "%d, %s, %d\n", rank, IPAddressToString(element.address), element.count);
}
else{
rank++;
if(rank>n)
break;
fprintf(outFileStream, "%d, %s, %d\n", rank, IPAddressToString(element.address), element.count);
valueHolder = element.count;
}
nodeIndex++;
}
Please note that I set the size of the array size in the main function before I use it.
Or, to put it simply, here's an example of what I want;
#include <iostream>
using namespace std;
struct node
{
int value;
node *left;
node *right;
};
class btree
{
public:
btree();
~btree();
void insert(int key);
void destroy_tree();
void inorder_print();
private:
void destroy_tree(node *leaf);
void insert(int key, node *leaf);
void inorder_print(node *leaf);
node *root;
};
btree::btree()
{
root = NULL;
}
btree::~btree()
{
destroy_tree();
}
void btree::destroy_tree(node *leaf)
{
if(leaf != NULL)
{
destroy_tree(leaf->left);
destroy_tree(leaf->right);
delete leaf;
}
}
void btree::insert(int key, node *leaf)
{
if(key < leaf->value)
{
if(leaf->left != NULL)
{
insert(key, leaf->left);
}
else{
leaf->left = new node;
leaf->left->value = key;
leaf->left->left = NULL;
leaf->left->right = NULL;
}
}
else if(key >= leaf->value)
{
if(leaf->right != NULL)
{
insert(key, leaf->right);
}
else
{
leaf->right = new node;
leaf->right->value = key;
leaf->right->right = NULL;
leaf->right->left = NULL;
}
}
}
void btree::insert(int key)
{
if(root != NULL)
{
insert(key, root);
}
else
{
root = new node;
root->value = key;
root->left = NULL;
root->right = NULL;
}
}
void btree::destroy_tree()
{
destroy_tree(root);
}
void btree::inorder_print()
{
inorder_print(root);
cout << "\n";
}
void btree::inorder_print(node *leaf)
{
if(leaf != NULL)
{
inorder_print(leaf->left);
cout << leaf->value << ",";
inorder_print(leaf->right);
}
}
int main(){
//btree tree;
btree *tree = new btree();
tree->insert(10);
tree->insert(6);
tree->insert(14);
tree->insert(5);
tree->insert(8);
tree->insert(11);
tree->insert(18);
tree->inorder_print();
delete tree;
}
This produces the following output at once:
5,6,8,10,11,14,18,
How can I get 5, then 6, then 8 etc, but each at a time, instead of all at once?
Any help offered will be appreciated!
CPP is complaining that "undefined reference to IPAddressAnalyzer::nodesArray"
This is probably because nodesArray is a static member variable, but you never declared storage for it. In some .cpp file, preferably one related to IPAddressAnalyzer, you should add the following line:
node *IPAddressAnalyzer::nodesArray;
But maybe just making it a non-static member would be even better.
I suggest you make use of the standard library instead of implementing your own tree structure, and use std::map and/or std::set instead. Your example of what you want can be rewritten like so:
#include <iostream>
#include <set>
int main(){
std::set<int> tree;
tree.insert(10);
tree.insert(6);
tree.insert(14);
tree.insert(5);
tree.insert(8);
tree.insert(11);
tree.insert(18);
for (auto &element: tree) {
std::cout << element << ',';
}
std::cout << '\n';
}

How to implement complete binary in c++?

I want to try make insertion of complete binary tree using recursion . I make a piece of code and I cannot catch problem why value not inserted. I make height function and count nodes function with help of these function and recursive call I want to insert new node in Complete binary tree. In main get root by using get root function then send to insert function
#include<iostream>
#include<math.h>
using namespace std;
struct node{
int data;
node *left,*right;
};
class cbt{
node *root;
public:
cbt()
{
root=NULL;
}
node* get_node()
{
return root;
}
node* newNode(int key)
{
node* temp1 = new node;
temp1->data = key;
temp1->left = temp1->right = NULL;
return temp1;
}
void CBT_inseration(node* temp,int data)
{
node *ptr;
ptr=newNode(data);
if(root==NULL)
{
root=ptr;
return;
}
else
{
height = f_height(temp->left);
int excepted_node = pow(2,height)-1;
int left_tree_node_count = countNumNodes(temp->left);
int right_tree_node_count = countNumNodes(temp->right);
if(left_tree_node_count==right_tree_node_count)
{
CBT_inseration(temp->left,data);
}
else if(excepted_node != left_tree_node_count)
{
if(temp->left == NULL)
{
temp->left = ptr;
return;
}else
{
CBT_inseration(temp->left,data);
}
}
else if(temp->right == NULL)
{
temp->right=ptr;
return;
}
else if(excepted_node != left_tree_node_count)
{
if(temp->left == NULL)
{
temp->left=ptr;
return;
}
else
{
CBT_inseration(temp->right,data);
}
}
}
}
void print(node *root) {
if (root == NULL)
return;
print(root->left);
cout << root->data << " ";
print(root->right);
}
};
int main()
{
cbt obj;
node *r=NULL;
obj.CBT_inseration(obj.get_node(),4);
obj.CBT_inseration(obj.get_node(),3);
obj.CBT_inseration(obj.get_node(),5);
obj.CBT_inseration(obj.get_node(),8);
obj.print(obj.get_node());
return 0;
}
You would need to go through a debugger to see what is wrong with your code. I will tell you how I would do this:
First, you need a function to check if the tree is full. We will reuse your functions to do this:
bool isTreeFull(node* head) {
return head != NULL && countNumNodes(head) == (1 << find_height(head)) - 1;
}
Then for inserting I have to check if the number of nodes on each side are the same. This tells me that I am allowed to move one level deeper on the left side. If the number of nodes aren't the same, then I only move on to insert on the right subtree if the left subtree is full:
void CBT_inseration(int data) {
root = insert(root, data);
}
node* insert(node* head, int data) {
if (head == NULL) {
head = newNode(data);
} else {
int leftCount = countNumNodes(head->left);
int rightCount = countNumNodes(head->right);
if (leftCount == rightCount) {
head->left = insert(head->left, data);
} else {
if (isTreeFull(head->left)) {
head->right = insert(head->right, data);
} else {
head->left = insert(head->left, data);
}
}
}
return head;
}
Then you would call it like:
cbt obj;
obj.CBT_inseration(4);
obj.CBT_inseration(3);
obj.CBT_inseration(5);
obj.CBT_inseration(6);
obj.CBT_inseration(8);
obj.print(obj.get_node()); // 6 3 8 4 5

Singly-Linked List Add Function - Read Access Violation

I'm trying to create a basic singly-linked list using a separate Node class and LinkedList class. I barely know what I'm doing as I've just started learning C++, so any help would be greatly appreciated.
The LinkedList part of the code runs on its own, but I'm sure there are some corrections to be made there too. My main problem is that, when trying to add to the linked list, I'm getting (at line 64 of LinkedList.h):
Exception thrown: read access violation. this->head was nullptr.
I'm using Microsoft Visual Studio 2015. Here's the code:
LinkedList.h (it's inline):
#pragma once
#include <iostream>
using namespace std;
class Node
{
private:
Node *next = NULL;
int data;
public:
Node(int newData) {
data = newData;
next = NULL;
}
Node() {
}
~Node() {
if(next)
delete(next);
}
Node(int newData, Node newNext) {
data = newData;
*next = newNext;
}
void setNext(Node newNext) {
*next = newNext;
}
Node getNext() {
return *next;
}
int getData() {
return data;
}
};
class LinkedList
{
private:
Node *head;
int size;
public:
LinkedList()
{
head = NULL;
size = 0;
}
~LinkedList()
{
}
void add(int numberToAdd)
{
head = new Node(numberToAdd, *head);
++size;
}
int remove()
{
if (size == 0) {
return 0;
}
else {
*head = (*head).getNext();
--size;
return 1;
}
}
int remove(int numberToRemove)
{
if (size == 0)
return 0;
Node *currentNode = head;
for (int i = 0; i < size; i++) {
if ((*currentNode).getData() == numberToRemove) {
*currentNode = (*currentNode).getNext();
return 1;
}
}
}
void print()
{
if (size == 0) {
return;
}
else {
Node currentNode = *head;
for (int i = 0; i < size; i++) {
cout << currentNode.getData();
currentNode = currentNode.getNext();
}
cout << endl;
}
}
};
List Tester.cpp
// List Tester.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include "LinkedList.h"
using namespace std;
int main()
{
LinkedList myList;
myList.add(4);
system("pause");
}
You are making copies where you should not:
This:
Node(int newData, Node newNext) {
data = newData;
*next = newNext;
}
should be:
Node(int newData, Node* newNext) {
data = newData;
next = newNext;
}
Because now this:
head = new Node(numberToAdd, *head);
becomes this:
head = new Node(numberToAdd, head);
and will work even if head is a null pointer. You may need to adjust your other code accordingly.
Your whole implementation is full of errors. It should look more like this instead:
#pragma once
#include <iostream>
class Node
{
private:
int data;
Node *next;
public:
Node(int newData, Node *newNext = NULL)
: data(newData), next(newNext)
{}
void setNext(Node *newNext) {
next = newNext;
}
Node* getNext() {
return next;
}
int getData() {
return data;
}
};
class LinkedList
{
private:
Node *head;
int size;
public:
LinkedList()
: head(NULL), size(0)
{
}
~LinkedList()
{
Node *currentNode = head;
while (currentNode)
{
Node *nextNode = currentNode->getNext();
delete currentNode;
currentNode = nextNode;
}
}
void add(int numberToAdd)
{
head = new Node(numberToAdd, head);
++size;
}
bool remove()
{
Node *currentNode = head;
if (!currentNode)
return false;
head = currentNode->getNext();
delete currentNode;
--size;
return true;
}
bool remove(int numberToRemove)
{
Node *currentNode = head;
Node *previousNode = NULL;
while (currentNode)
{
if (currentNode->getData() == numberToRemove)
{
if (head == currentNode)
head = currentNode->getNext();
if (previousNode)
previousNode->setNext(currentNode->getNext());
delete currentNode;
return true;
}
previousNode = currentNode;
currentNode = currentNode->getNext();
}
return false;
}
void print()
{
Node *currentNode = head;
if (!currentNode) return;
do
{
std::cout << currentNode->getData();
currentNode = currentNode->getNext();
}
while (currentNode);
std::cout << std::endl;
}
};
Which can then be simplified using the std::forward_list class (if you are using C++11 or later):
#pragma once
#include <iostream>
#include <forward_list>
#include <algorithm>
class LinkedList
{
private:
std::forward_list<int> list;
public:
void add(int numberToAdd)
{
list.push_front(numberToAdd);
}
bool remove()
{
if (!list.empty())
{
list.pop_front();
return true;
}
return false;
}
bool remove(int numberToRemove)
{
std::forward_list<int>::iterator iter = list.begin();
std::forward_list<int>::iterator previous = list.before_begin();
while (iter != list.end())
{
if (*iter == numberToRemove)
{
list.erase_after(previous);
return true;
}
++previous;
++iter;
}
return false;
}
void print()
{
if (list.empty()) return;
std::for_each(list.cbegin(), list.cend(), [](int data){ std::cout << data });
std::cout << std::endl;
}
};

Why isn't my function returning the count? (Binary Tree)

Everything in my program works perfectly, except it is not showing the count for the field. I tried to change some codes but it does not seem to display it in the output. It seems like a easy mistake or something obviously but I have no idea why it doesn't display it. Can someone help?
#include <iostream>
using namespace std;
template<class T>
class BinaryTree
{
struct Node
{
T data;
Node* leftChild;
Node* rightChild;
Node(T dataNew)
{
data = dataNew;
leftChild= NULL;
rightChild = NULL;
}
};
private:
Node* root;
void Add(T new_Data, Node* &the_Root)
{
if (the_Root == NULL)
{
the_Root = new Node(new_Data);
return;
}
if (new_Data < the_Root->data)
Add(new_Data, the_Root->leftChild);
else
Add(new_Data, the_Root->rightChild);
}
int countTree(Node* the_Root)
{
if (the_Root == NULL)
return 0;
else {
int count = 1;
count += countTree(the_Root->leftChild);
count += countTree(the_Root->rightChild);
return count;
}
}
void PrintTree(Node* the_Root)
{
if (the_Root != NULL)
{
cout << the_Root->data <<" ";
PrintTree(the_Root->leftChild);
PrintTree(the_Root->rightChild);
}
}
public:
BinaryTree()
{
root = NULL;
}
void AddItem(T new_Data)
{
Add(new_Data, root);
}
int countTree()
{
return countTree(root);
}
void PrintTree()
{
PrintTree(root);
}
};
int main()
{
BinaryTree<int> *myBT = new BinaryTree<int>();
myBT->AddItem(6);
myBT->AddItem(5);
myBT->AddItem(4);
myBT->AddItem(18);
myBT->AddItem(6);
myBT->PrintTree();
myBT->countTree();
}
The count won't be shown simply because you didn't write any code to show the count.
Try changing myBT->countTree(); to cout << myBT->countTree();, and you will see the count printed.
You aren't actually doing anything with the result of myBT->countTree(). Try printing it:
std::cout << myBT->countTree() << std::endl;

Write a program, which converts the expression a b + c d e + * * into an expression tree using stack.

description
I don't know how to do this task.... but i just created a tree and enter value..can anyone please help me to do this task...the Stack is also of node type and we have to push value of operators like ab+ so we will push a as node then b as node and when + will come we make a tree and a and b will be its leafs node.
.Code
#include<iostream>
using namespace std;
class Node{
public:
int data;
Node *left;
Node *right;
Node()
{
data = 0;
left = NULL;
right = NULL;
}
};
class Tree
{
Node *root;
void insert(int d, Node *node)
{
if (d < node->data)
{
if (node->left == NULL)
{
Node *leaf = new Node();
leaf->data = d;
node->left = leaf;
}
else
{
insert(d, node->left);
}
}
else
{
if (node->right == NULL)
{
Node *leaf = new Node();
leaf->data = d;
node->right = leaf;
}
else
{
insert(d, node->right);
}
}
}
void inOrderDisplay(Node *subRoot)
{
if (subRoot != NULL)
{
inOrderDisplay(subRoot->left);
cout << subRoot->data << " ";
inOrderDisplay(subRoot->right);
}
}
void postOrderDisplay(Node *subRoot)
{
if (subRoot != NULL)
{
postOrderDisplay(subRoot->left);
postOrderDisplay(subRoot->right);
cout << subRoot->data << " ";
}
}
void preOrderDisplay(Node *subRoot)
{
if (subRoot != NULL)
{
cout << subRoot->data << " ";
preOrderDisplay(subRoot->left);
preOrderDisplay(subRoot->right);
}
}
void deleteSubtree(Node *subRoot)
{
if (subRoot != NULL)
{
deleteSubtree(subRoot->left);
deleteSubtree(subRoot->right);
cout << "\ndeleting: " << subRoot->data;
delete subRoot;
subRoot = NULL;
}
}
public:
Tree()
{
root = NULL;
}
~Tree()
{
deleteAll();
}
void insert(int d)
{
if (root == NULL)
{
Node *leaf = new Node();
leaf->data = d;
root = leaf;
}
else
{
insert(d, root);
}
}
void inOrderDisplay()
{
inOrderDisplay(root);
}
void postOrderDisplay()
{
postOrderDisplay(root);
}
void preOrderDisplay()
{
preOrderDisplay(root);
}
void deleteAll()
{
deleteSubtree(root);
}
};
.Main Class:
#include<iostream>
#include"task1.h"
using namespace std;
void main()
{
Tree tree;
tree.insert(10);
tree.insert(6);
tree.insert(14);
tree.insert(5);
tree.insert(8);
tree.insert(11);
tree.insert(18);
cout << endl;
system("pause");
//tree.deleteAll();
}
Based on the code you have here, you only have a void insert(int d, Node *node) function, no void insert(operator o, Node *node) function.
I think this shows that you missed an important point here. Every node in the tree can either be an integer (as you did) or an operator. In both cases, I'd call it a string. Every node that is not a leaf must be an operator, and all leafs must be integers (or strings that represents operators/integer in our case).
Then, iterating over your input, the first three item should result in something like:
+
/ \
a b
The next step would be to build more sub trees (not sure of the definition of the input you have), keep them in your stack and then construct more inner nodes of the tree.
So if the tree I showed above is called Tree(+) (for ease of use), and the initial stack was [a,b,+,c,d,e,*,*], then after one iteration you'll have [Tree(+),c,d,e,*,*] and you continue from there.