I'm a beginner to c++ and am having problems with finding the minimal element of a BST. The BST is implemented in this way:
class Tree{
struct Node {
int Element;
Node *Left, *Right;
Node(int Element) : Element(Element), Left(0), Right(0){}
};
Node *Root;
void InOrder(void(*Action)(int&), Node *Current);
void Destroy(Node *Current);
public:
Tree() : Root(0){}
void Insert(int Element);
void InOrder(void(*Action)(int&)) {InOrder(Action,Root);}
void Destroy() {Destroy(Root);}
};
The InOrder, Destroy and Insert methods are implemented like this:
void Tree::Insert(int Element) {
Node *NewElement = new Node(Element);
if(!Root) Root = NewElement;
else {
Node *Previous, *Current = Root;
while(Current) {
Previous = Current;
if(Element < Current->Element) Current = Current->Left;
else Current = Current->Right;
}
if(Element < Previous->Element) Previous->Left = NewElement;
else Previous->Right = NewElement;
}
}
void Tree::InOrder(void(*Action)(int&),Node *Current) {
if(Current) {
InOrder(Action,Current->Left);
Action(Current->Element);
InOrder(Action,Current->Right);
}
}
void Tree::Destroy(Node *Current) {
if(Current) {
Destroy(Current->Left);
Destroy(Current->Right);
delete Current;
}
}
And the main function and function which I use to print the numbers look like this:
void Print(int &e) {
cout << e << endl;
}
int main() {
Tree t;
while(1) {
int Number;
cout << "Insert number (insert 0 to end): ";
cin >> Number;
if(Number == 0) break;
t.Insert(Number);
}
t.InOrder(Print);
t.Destroy();
getch();
}
As you may noticed, the InOrder method is implemented also, maybe it can be used in some way to help solve my problem... Sorry for my bad English :/
The minimal value would be the first value that calls Action in the above code. Go left as far as you can, and the minimal value you shall find...
Related
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';
}
I desperately need help finding the problem in my code, I'm sure it's narrowed down to the countLeaves function. I can't seem to get it to print out no matter how I alter it. I'm pretty new to C++ but I'd really appreciate anything anyone can offer me! I will post the header, function, and main in that order.
#include <iostream>
//#include<stack>
//#include<queue>
#ifndef BSTFunction
#define BSTFunction
using namespace std;
typedef int num;
class Node{
public:
num info;
Node* left;
Node* right;
Node(); // Valuetype to num
Node(num);
};
class BST{
public:
Node* findNode(num);
Node* findParent(num);
Node* findrightnode(Node*);
void inorder(Node*);
Node* root;
Node* curr;
//Was public:
BST();
void insert(num);
void inorderTraversal(); //was traverse
num search();
void custom_print();
int countLeaves(Node* T);
};
#endif
Function.cpp
#include <iostream>
#include <queue>
#include "BSTFunction.hpp"
Node::Node(){
left=right=NULL;
}
Node::Node(num val){
info=val;
left=right=NULL;
}
//constructor
BST::BST(){
root=curr=NULL;
}
//insert a node with value val in tree
void BST::insert(num val){
if(root==NULL)
root = new Node(val);
else{
Node* p =findNode(val);
if(p==0) {
//cout<<"fine1";
Node* parent=root;
if (p != root)
parent = findParent(val);
if(val>parent->info) parent->right=new Node(val);
else parent->left=new Node(val);
}//cout<<"fine2";
}
}
//remove the node if value is val
//fins node with a value key
Node* BST::findNode(num key){
Node* p =root;
while((p!=NULL)&&(p->info!=key)){
if(key<p->info)p=p->left;
else p=p->right;
}
return p;
}
//find parent of a node with value key
Node* BST::findParent(num key){
Node* p =root;
Node* q=0;
while((p!=NULL)&&(p->info!=key)){
q=p;
if(key<p->info)p=p->left;
else p=p->right;
}
return q;
}
//finds the most right of a node p(means immediate succesor of p in inorder representation)
//Node* BST::findrightnode(Node* p){
// Node* righty=p;
// while(righty->right!=NULL)
// righty=righty->right;
// return righty;
//}
void BST::inorder(Node* p){
if(p!=NULL){
inorder(p->left);
cout<<p->info<<" ";
inorder(p->right); }
}
void BST::inorderTraversal(){
cout<<endl<<"Inorder: ";
inorder(root);
cout<<endl;
}
//to print tree hightwise i.e. all nodes at h1, then all nodes at h2, then at h3
void BST::custom_print(){
//Node* temp;
if(root==NULL)
return;
queue<Node*> Q;
Q.push(root);
//Q.push(NULL);
while(!Q.empty()){
curr=Q.front();
cout<<curr<<" ";
Q.pop();
Q.push(curr->left);
Q.push(curr->right);
}
}
int BST::countLeaves(Node *T)
{
if(T ==NULL) //if T is empty, return0
{
return(0);
}
else if(T -> left == NULL && T-> right == NULL) //if T has0 children, then it is a leaf
{
return(1);
}
else
{
return countLeaves(T -> left) + countLeaves(T -> right); //recursive call to find more leaves
}
}
Main.cpp
#include<iostream>
#include "BSTFunction.hpp"
int main()
{
BST leaves;
leaves.insert(24);
leaves.insert(43); //The code will take all of these numbers entered into the main function and put them in traversal order, much like it could under any order (post or pre) if needed. (Note to self: Not needed for this assignment)
leaves.insert(82);
leaves.insert(22);
leaves.insert(12);
leaves.insert(92);
leaves.insert(68);
leaves.insert(20);
leaves.insert(4);
cout << "These are the in order leaves for the Bianary Search Tree. " << endl;
leaves.inorderTraversal();
cout << "The number of leaves are: " << endl;
leaves.countLeaves()
//leaves.custom_print();
return 0;
}
The problem in your code is that you have an argument in your countLeaves() function-
int BST::countLeaves(Node *T)
When you call this function from your main, it doesn't have an
argument to give to countLeaves(). It throws an error as it doesn't
receive any parameter.
As for the solution, you'll have to create a Node object in your main and send it as an argument. You'll have to worry about what and how you are going to do all this. There seems to be a few errors both in logic and syntax. (I commented your countLeaves() call and it threw many errors.
Recommend using debugger.
Try to print values and "Function entered" print statements to make it easier to find mistakes in your program if you cannot use debugger at the moment.
Hope this was helpful.
I am trying to just change the data of the Node to swap the nodes. Any help is appreciated. Maybe it's a basic mistake i am new to c++.
I know the method to SwapNodes using 4 pointer and that stuff sounds cool, but what's the problem in this?
#include <iostream>
using namespace std;
class Node
{
int data;
Node *next;
public:
Node(int val)
{
data=val;
next=NULL;
}
int Data(){return data;};
void ChangeData(int newData){data=newData;};
void setNext(Node *NEXT){next=NEXT;};
Node *Next(){return next;};
};
class LinkedList
{
Node *root;
public:
LinkedList();
void insert(int pos,int b);
void deleteNode(int a);
void outputList();
void SwapNodes(int x, int y);
void reverse();
};
LinkedList::LinkedList()
{
root=NULL;
}
void LinkedList::insert(int pos,int b)
{
Node *temp=root;
Node *newnode=new Node(b);
if(pos==0)
{
if(root==NULL)
{
root=newnode;
return;
}
newnode->setNext(root);
root=newnode;
return;
}
for (int i = 1; i <pos ; ++i)
{
temp=temp->Next();
}
newnode->setNext(temp->Next());
temp->setNext(newnode);
}
void LinkedList::deleteNode(int a)
{
Node *temp=root;
Node *agla=root->Next();
if(temp->Data()==a)
{
root=root->Next();
free(temp);
}
if(agla->Data()==a)
{
temp->setNext(agla->Next());
free(agla);
return;
}
while(agla!=NULL && agla->Data()!=a)
{
temp=agla;
agla=agla->Next();
}
if(agla==NULL)
{
cout << "key not found";
}
temp->setNext(agla->Next());
free(agla);
}
void LinkedList::SwapNodes(int x,int y)
{
Node *temp1=root;
Node *temp2=root;
if(x==y)return;
while(temp1!=NULL && (temp1)->Data()!=x)
{
(temp1)=(temp1)->Next();
}
temp1->ChangeData(y);
while(temp2!=NULL && (temp2)->Data()!=y)
{
(temp2)=(temp2)->Next();
}
if(temp1==NULL || temp2==NULL)
{
return;
}
(temp2)->ChangeData(x);
}
void LinkedList::reverse()
{
if(root == NULL) return;
Node *prev = NULL, *current = NULL, *next = NULL;
current = root;
while(current != NULL){
next = current->Next();
current->setNext(prev);
prev = current;
current = next;
}
root = prev;
}
void LinkedList::outputList()
{
Node *temp=root;
if(temp==NULL)
{
cout << "empty";
return;
}
while(temp!=NULL)
{
cout<< temp->Data()<< " ";
temp=temp->Next();
}
cout << "\n";
}
int main(int argc, char const *argv[])
{
LinkedList newList;
newList.insert(0,4);
newList.insert(1,5);
newList.insert(2,7);
newList.insert(3,9);
newList.insert(4,12);
newList.outputList();
newList.insert(2,6);
newList.outputList();
newList.deleteNode(5);
newList.outputList();
newList.SwapNodes(7,9);
newList.outputList();
newList.reverse();
newList.outputList();
return 0;
}
In
void LinkedList::SwapNodes(int x,int y)
{
Node *temp1=root;
Node *temp2=root;
if(x==y)return;
while((temp1)->Data()!=x)
{
(temp1)=(temp1)->Next();
}
temp1->ChangeData(y);
while((temp2)->Data()!=y)
{
(temp2)=(temp2)->Next();
}
(temp2)->ChangeData(x);
}
You are just undoing the work you already did.
while((temp1)->Data()!=x)
{
(temp1)=(temp1)->Next();
}
temp1->ChangeData(y);
Is going to find x and then set it to y. Then you go to do
while((temp2)->Data()!=y)
{
(temp2)=(temp2)->Next();
}
(temp2)->ChangeData(x);
Which finds that y you just created (as long as there wasn't a previous y) and sets it back to x. What you need to do is find the nodes to swap first and then swap their data. A simple refactor to
void LinkedList::SwapNodes(int x,int y)
{
Node *temp1=root;
Node *temp2=root;
if(x==y)return;
while((temp1)->Data()!=x)
{
(temp1)=(temp1)->Next();
}
while((temp2)->Data()!=y)
{
(temp2)=(temp2)->Next();
}
temp1->ChangeData(y);
(temp2)->ChangeData(x);
}
Should work. You also should add add error handling code in case x or y does no exist.
Not sure why you are using the parentheses everywhere but
(temp1)=(temp1)->Next();
Can just be written as
temp1 = temp1->Next();
while((temp1)->Data()!=x)
{
(temp1)=(temp1)->Next();
}
temp1->ChangeData(y);
Loops until it finds a link valued at x. Then overwrites the value with y. OK. But now you have two ys in the linked list, so odds are decent that
while((temp2)->Data()!=y)
{
(temp2)=(temp2)->Next();
}
(temp2)->ChangeData(x);
will simply find the Node that which was x and change it back to x.
while((temp1)->Data()!=x)
{
(temp1)=(temp1)->Next();
}
while((temp2)->Data()!=y)
{
(temp2)=(temp2)->Next();
}
temp1->ChangeData(y);
temp2->ChangeData(x);
Will prevent that by finding both x and y nodes before updating their value, but has other problems. Not the least of which is what happens when you hit the end of the list without finding x or y?
I'd rethink the linking logic because there doesn't seem to be any way to tell that you've hit the end of the list. Typical solution are to set next for the last Node to NULL or nullptr and test with something like
while(temp1 != nullptr)
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.
Here is my code:
#include<iostream.h>
#include<conio.h>
#include<stdlib.h>
#include<process.h>
struct tree_node
{
tree_node *left;
tree_node *right;
int data;
char r;
} ;
class bst
{
tree_node *root;
public:
bst()
{
root=NULL;
}
int isempty()
{
return(root==NULL);
}
void insert(int item);
void inordertrav();
void inorder(tree_node *);
void postordertrav();
void postorder(tree_node *);
void preordertrav();
void preorder(tree_node *);
int search(tree_node * ,int);
};
void bst::insert(int item)
{
tree_node *p=new tree_node;
tree_node *previous;
p->data=item;
p->left=NULL;
p->right=NULL;
previous=NULL;
if(isempty())
root=p;
else
{
tree_node *current;
current=root;
while(current!=NULL)
{
previous=current;
if(item<current->data)
current=current->left;
else
current=current->right;
}
if(item<previous->data)
previous->left=p;
else
previous->right=p;
}
}
int bst::search(tree_node* root,int data) {
int r;
if(root == NULL) {
// r='f';
return 0;
}
else if (root != NULL){
if(root->data == data) {
// r='t';
return 1;
}
}
else if(data <= root->data) {
return search(root->left,data);
}
else {
return search(root->right,data);
}
}
void main()
{
int digit;
bst b;
tree_node *root;
/*b.insert(52);
b.insert(25);
b.insert(50);
b.insert(15);
b.insert(40);
b.insert(45);
b.insert(20); */
cout<<"insert the nodes in the BT";
cout<<"enter integer: to quit enter 0";
cin>>digit;
while (digit!=0)
{
b.insert(digit);
cin>>digit;
}
cout<<"inorder"<<endl;
b.inordertrav();
cout<<endl<<"postorder"<<endl;
b.postordertrav();
cout<<endl<<"preorder"<<endl;
b.preordertrav();
int number;
cout<<"Enter number be searched\n";
cin>>number;
//If number is found, print "FOUND"
int c;
c=b.search(root,number);
cout<<"returned value"<<c;
if (c==1) cout<<"Found\n";
else cout<<"Not Found\n";
getch();
}
The search function is always returning the same value whether it is in the BST or not.
Please help me to figure out the error.
The above code has no compilation error.
All other functions except search function are working fine.
But the search function is not working as required to search whether the element is in the Binary Search tree or not.
Your code invoke UB.
tree_node *root;
...
c=b.search(root,number); // root is uninitialized
To solve this add a new function:
class bst
{
...
int search(tree_node * ,int);
int search(int v) {
return search(root, v);
}
};
Also in bst::search function:
else //if (root != NULL){ Comment this condition
if(root->data == data) {
// r='t';
return 1;
}
//} Comment this line
This condition is not only redundant but also make some code flow paths return without value.