I was wondering how I would add a counter that represents the number of comparisons in my BST. I added a counter but my printTree function for some reason I keep getting 0 for the count. Am I suppose to count the number of comparisons made in the print function? Or should I have a separate function specifically for counting the number of comparisons made?
#include <iostream>
#include <cstdlib>
#include <fstream>
using namespace std;
struct node
{
int data;
node* left;
node* right;
};
node* root = NULL;
node* createLeaf(int data)
{
node* n = new node;
n->data = data;
n->left = NULL;
n->right = NULL;
return n;
}
void addLeaf(node* &curr, int data)
{
//If curr = NULL then add node
if(curr == NULL)
{
curr = createLeaf(data);
}
//Left(Less than)
else if(data <= curr->data)
{
addLeaf (curr->left, data);
}
//Right(greater than)
else if(data >= curr->data)
{
addLeaf(curr->right, data);
}
}
int printTree(node* Ptr, ofstream& NewData, int count)
{
//Check if tree is empty
if(root != NULL)
{
return count++;
if(Ptr->left != NULL)
{
printTree(Ptr->left, NewData, count);
}
NewData << Ptr->data; //Store Data in output file
NewData << endl;
cout << Ptr->data << " ";
if(Ptr->right != NULL)
{
printTree(Ptr->right, NewData, count);
}
}
else
{
cout << "The Tree is empty\n";
}
return Ptr->data;
}
int main()
{
ifstream dataFile;
dataFile.open("Data.txt.");
int temp, count;
count = 0;
while(dataFile)
{
dataFile >> temp;
addLeaf(root, temp);
}
dataFile.close();
ofstream NewData;
NewData.open("NewData.txt");
count = printTree(root, NewData, count);
cout << "count:" << count;
NewData.close();
system("PAUSE");
return 0;
}
Simply pass the count variable by reference (Or use a pointer. Example uses pass by reference) and then increment without returning and this will give you a simple way of counting the number of comparisons. Edited snippets of your code are below.
Note: For future reference post incrementing value to be returned will do nothing if it is being returned. e.g. use return ++count; instead of return count++;. This is why you where getting zero as the value of your count variable. A simple way of explaining this behavior is that when you return a post-incremented value it returns the value and exists that function before incrementing it. Although from what I understand of the code you did not really want to be returning the count variable.
int printTree(node* Ptr, ofstream& NewData, int &count)
{ // ^ The & specifies that is to be passed
// by reference.
//Check if tree is empty
if(root != NULL)
{
// No longer returns instead just increments.
count++;
// Your code here.
}
// Your code here.
}
int main()
{
int count = 0;
// The rest of your code here ....
// Stores the return value from print tree root "ptr->data"
int data = 0;
// New caller will modify count as it is passed by reference, but will "return ptr->data;"
data = printTree(root, NewData, count);
cout << "count:" << count;
system("PAUSE");
return 0;
}
I'd do it by defining a tiny class that was devoted primarily to counting comparisons:
template <class T>
struct holder {
static int count;
T t;
holder(T T) : t(t) {}
operator T() const { return t; }
operator <(T const &r) { ++count; return t < r.t; }
};
int holder::count = 0;
Then a node would hold instances of these instead of holding ints directly:
struct node {
holder<int> data;
node *left;
node *right;
};
Do your work with your tree, and when you want to know the number of comparisons you've done so far, look at holder<int>::count; to get it.
Related
I am trying to implement a simple open hash in c++ for the sake of learning. I am getting very confused about the interaction of functions with array pointers, and I am at the end of my wits.
The code:
struct node{
int data;
node* next;
node* prev;
bool state;
node(){
prev = next = NULL;
state = true;
}
};
//state true means empty, state false means full.
void insert(node *array,int value){
node *current = array;
if(array->state == true){
array->data = value;
array->state = false;
} else {
node* add = new node();
add->data = value;
add->state = false;
while(current->next != NULL){
current = current->next;
}
current->next = add;
add->prev = current;
}
}
void display(node *array, int size){
node *show = new node();
for(int i = 0; i< size; i++){
if(array->state == false){
cout<<array->data;
show = array;
while(show->next != NULL){
show = show->next;
cout<<" --> "<<show->data;
}
} else {
cout<<"Empty.";
}
cout<<"\n\n";
}
}
int main(){
int size;
cout<<"Enter size of the hash table: ";
cin>>size;
node *array = new node[size];
int value;
cout<<"Enter Value: ";
cin>>value;
int index = value%size;
//inserting single value
insert(&array[index],value);
//Hash table output.
display(array,size);
return 0;
}
When I run this code, instead of showing "empty" in places where the array's state is empty, it seems as if the entire array has the same value. The problem lies in the insert function, but I cannot figure it out.
You can simplify this by making the Hashtable an array of pointers to Node. A nullptr then means the slot is empty and you don't have empty and full nodes. Also Nodes only need a next pointer and usually new entries are added to the beginning of the buckets instead of the end (allows duplicate entries to "replace" older ones). Inserting at the beginning of a list becomes real easy with Node **.
#include <cstddef>
#include <iostream>
struct Table {
struct Node {
Node * next;
int data;
Node(Node **prev, int data_) : next{*prev}, data{data_} {
*prev = this;
}
};
std::size_t size;
Node **tbl;
Table(std::size_t size_) : size{size_}, tbl{new Node*[size]} { }
~Table() {
for (std::size_t i = 0; i < size; ++i) {
Node *p = tbl[i];
while(p) {
Node *t = p->next;
delete p;
p = t;
}
}
delete[] tbl;
}
void insert(int value) {
Node **slot = &tbl[value % size];
new Node(slot, value);
}
void display() const {
for(std::size_t i = 0; i < size; i++) {
std::cout << "Slot " << i << ":";
for (const Node *node = tbl[i]; node; node = node->next) {
std::cout << " " << node->data;
}
std::cout << std::endl;
}
}
};
int main(){
std::size_t size;
std::cout << "Enter size of the hash table: ";
std::cin >> size;
Table table{size};
int value;
std::cout << "Enter Value: ";
std::cin >> value;
//inserting single value
table.insert(value);
//Hash table output.
table.display();
return 0;
}
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 am tasked with implementing a new class function called bool List::largest_value(int &largest) within a given class List. The instruction is:
If the list is not empty, put the largest value in the largest
parameter and return true. If the list is empty, return false.
My question is, how do I find the largest value within a parameter?
Here is what I have so far for bool List::largest_value(int &largest):
// Fill in the functions at the bottom of this file
//
#include <iostream>
#include <climits>
using namespace std;
#include "list.h"
// on some machines member variables are not automatically initialized to 0
List::List()
{
m_head = NULL;
}
// delete all Nodes in the list
// since they are dynamically allocated using new, they won't go away
// automatically when the list is deleted
// Rule of thumb: destructor deletes all memory created by member functions
List::~List()
{
while (m_head)
{
Node *tmp = m_head;
m_head = m_head->m_next;
delete tmp;
}
}
// always insert at the front of the list
// Note: this works even in the SPECIAL CASE that the list is empty
void List::insert(int value)
{
m_head = new Node(value, m_head);
}
// iterate through all the Nodes in the list and print each Node
void List::print()
{
for (Node *ptr = m_head; ptr; ptr = ptr->m_next)
{
cout << ptr->m_value << endl;
}
}
void List::compare(int target, int &less_than, int &equal, int &greater_than)
{
Node *temp = m_head;
less_than = 0;
equal = 0;
greater_than = 0;
while(temp != NULL)
{
if(temp->m_value > target)
{
greater_than++;
}
else if(temp->m_value < target)
{
less_than++;
}
else if(temp->m_value == target)
{
equal++;
}
temp = temp-> m_next;
}
}
bool List::largest_value(int &largest)
{
Node *temp = m_head;
largest = INT_MIN;
if(temp == NULL)
{
return false;
}
while(temp != NULL)
{
if(temp->m_value > largest)
{
largest = temp->m_value;
}
temp = temp->m_next;
}
return true;
}
Here is the given class List:
class List
{
public:
List();
~List();
void insert(int value); // insert at beginning of list
void print(); // print all values in the list
void compare(int target, int &less_than, int &equal, int &greater_than);
bool largest_value(int &largest);
private:
class Node
{
public:
Node(int value, Node *next)
{m_value = value; m_next = next;}
int m_value;
Node *m_next;
};
Node *m_head;
};
Main.cpp:
#include <iostream>
using namespace std;
#include "list.h"
int main()
{
List list;
int value;
// read values and insert them into list
while (cin >> value)
{
list.insert(value);
}
int largest;
bool result = list.largest_value(largest);
if (result == false)
{
cout << "empty list" << endl;
return 1;
}
else
{
cout << "The largest value you entered is: " << largest << endl;
}
}
My code compiles and runs, however I keep receiving the output empty list. I honestly have no idea what I need to change in my bool List::largest_value(int &largest)function. I am still very new to linked lists. Any help would be appreciated
For an exercize, I want to print out a tree data structure that is based on Node objects. This means, every object has a vector nodes that again holds other objects of type Node. But for some reason, when I let print out this->get_nr_children of the leaf nodes which basically just returns nodes.size(), I get completely random (negative) Integers where it should actually return 0. The even more interesting part: Every time I compile and execute, it prints out different Integers that alway are some low negative numbers. I do not have a clue what is happening!
Node.h
#include <string>
#include <vector>
using namespace std;
class Node
{
public:
virtual ~Node();
Node(string name = "");
string get_name() const;
void set_name(string& new_name);
int get_nr_children() const;
Node* get_child(int i) const;
void add_child(Node child);
void create_complete_tree(int nr_child_nodes, int tree_depth);
void print();
private:
string name;
static int node_id;
vector<Node> nodes = {};
};
Node.cpp
#include "node.h"
#include <sstream>
using namespace std;
Node::Node(string name) {
node_id++;
nodes = {};
if (name == "") {
stringstream str_sm;
str_sm << (node_id);
string node_id_str = str_sm.str();
this->name = "node_" + node_id_str;
} else {
this->name = name;
}
}
Node::~Node() {
nodes.clear();
// node_id = 0;
}
int Node::node_id = 0;
string Node::get_name() const {
return name;
}
void Node::set_name(string& new_name) {
this->name = new_name;
}
int Node::get_nr_children() const {
return nodes.size();
}
Node* Node::get_child(int i) const {
if (i >= nodes.size()) {
return NULL;
}
Node node = nodes[i];
Node *ptrNode = &node;
return ptrNode;
}
void Node::add_child(Node child) {
nodes.push_back(child);
}
void Node::create_complete_tree(int nr_child_nodes, int tree_depth) {
tree_depth--;
if (tree_depth <= 0) {
return;
}
for (int i = 0; i < nr_child_nodes; i++) {
Node* node = new Node();
this->add_child(*node);
node->create_complete_tree(nr_child_nodes, tree_depth);
}
}
void Node::print() {
cout << this->get_name() << "\n";
cout << "I got this many children " << this->get_nr_children();
for (int i = 0; i < this->get_nr_children(); i++) {
cout << "\t";
this->get_child(i)->print();
cout << "\n";
}
}
main.cpp
#include <iostream>
#include "node.cpp"
using namespace std;
int main() {
Node* root = new Node("root");
Node* left_child = new Node("left child");
Node* right_child = new Node("right child");
root->add_child(*left_child);
root->add_child(*right_child);
root->print();
return 0;
}
When I execute it I get:
root I got this many children 2 left child I got this many children
-62802357 right child I got this many children -62802357
Process finished with exit code 0
Your problem stems from
this->get_child(i)->print();
get_child returns a pointer to a local object. That object is destroyed when the function returns so the call to print on that returned Node is working with an already destroyed Node.
What you need to do is return a pointer directly to the vector element like
Node* Node::get_child(int i) /*const*/ { // cant be const for the return
if (i >= nodes.size()) {
return NULL;
}
return &nodes[i];
}
Node* Node::get_child(int i) const {
if (i >= nodes.size()) {
return NULL;
}
Node node = nodes[i];
Node *ptrNode = &node;
return ptrNode;
}
Above you return a pointer to destroyed local Node node after get_child(i) returned. Correct code is below, that returns a pointer to a child in the vector.
Node* Node::get_child(int i) const {
if (i >= nodes.size()) {
return NULL;
}
return &nodes[i];
}
main could be implemented much easier without pointers and memory leaks.
int main() {
Node root("root");
root.add_child(Node("left child"));
root.add_child(Node("right child"));
root.print();
return 0;
}
The problem is with the function Node* Node::get_child(int i) const. It returns a pointer to an object that is destroyed by the end of the function call.
Node* Node::get_child(int i) const {
if (i >= nodes.size()) {
return NULL;
}
Node node = nodes[i]; // <- node is a copy of nodes[i]
Node *ptrNode = &node;
return ptrNode; // <- returns a pointer to node
} // <- local objects are destroyed, including node
You must return a pointer to the actual element from the vector.
Node* Node::get_child(int i) const {
if (i >= nodes.size()) {
return NULL;
}
return &nodes[i]; // <- Returns the address of the actual node
}
I'm required to traverse through a singly linked list and find the negative nodes, delete them and return the number of delete nodes.
This is the code i have so far, but I always get counter=1 returned from the function
Is there anything wrong in the for loops and if statements, or is it something else
bool IntSLList::DeleteNegativeNodes()
{
int counter=0;
if(IsEmpty() == true)
counter++;
if(head->val<0)
{
DeleteFromHead();
counter++;
}
if(tail->val<0)
{
DeleteFromTail();
counter++;
}
IntSLLNode *node, *pred, *tmp;
node = pred = NULL;
for(pred = head, node = head->next;
node != NULL;
node = node->next, pred = pred->next)
{
if(node->val<0)
{
node->flag = 1;
}
}
for(tmp = head; tmp != NULL; tmp = tmp->next)
{
if(tmp->flag==1)
counter++;
delete tmp;
}
return counter;
}
int main()
{
int n,x,z;
IntSLList list1;
cout <<"Insert number of nodes u'd like inserted in list" << endl;
cin >> n;
for(int i=0;i<n;i++)
{
cin >> x;
list1.AddToTail(x);
}
z=list1.DeleteNegativeNodes();
cout << "Number of negative deletes nodes is : " << z << endl;
}
The problem is in the type of the return value. Check the signature of the method:
bool IntSLList::DeleteNegativeNodes()
Return type is bool there. When you return counter of type int from your method it's implicitly converted to bool. Zero value becomes false. All other values become true.
On the caller side:
z=list1.DeleteNegativeNodes();
bool value is implicitly converted to int. Because of it you get 1.
Change the return type of DeleteNegativeNodes to int to fix the problem.
In the second for you have
if(tmp->flag==1)
And I think you have to use
if(node->flag==1)