Creating a n-ary tree - c++

I am trying to create a n-ary tree with a vector of the children.
This is what I have gotten so far.
In the node.h file I have this:
#include <vector>
#include <string>
using namespace std;
class Node{
private:
Node *parent;
vector <Node*> children;
int data;
public:
Node();
Node(Node parent, vector<Node> children);
Node(Node parent, vector<Node> children, int data);
Node * GetParent();
void SetChildren(vector<Node> children);
vector<Node>* GetChildren();
void AddChildren(Node children);
void SetData(int data);
int GetData();
bool IsLeaf();
bool IsInternalNode();
bool IsRoot();
};
And this is my node.cpp file.
#include "node.h"
Node::Node(){
this->parent = NULL;
this->children = NULL;
this->data = 0;
}
Node::Node(Node parent, vector<Node> children){
this->parent = &parent;
this->children = &children;
}
Node::Node(Node parent, vector<Node> children, int data){
this->parent = &parent;
this->children = &children;
this->data = data;
}
Node* Node:: GetParent(){
return this->parent;
}
void Node::SetChildren(vector<Node> children){
this->children = &children;
}
vector<Node> * Node::GetChildren(){
return this->children;
}
void Node::AddChildren(Node children){
this->children.push_back(children);
}
void Node::SetData(int data){
this->data = data;
}
This obviously doesn't work. My main problem is that I am not quite sure how to handle the vector for the children. I wrote this following some tutorials online, but as you can see I am super confused.

The main (and possibly only) problem in your code is that you defined your Node class to manipulate nodes by pointers (Node*) :
class Node{
private:
Node *parent;
vector <Node*> children;
But your methods are manipulating nodes by values (Node).
As instance, in the constructors :
Node::Node(Node parent, vector<Node> children){
this->parent = &parent;
Storing the address of the parent parameter won't work, it's a temporary object, you'll need to pass a Node* parent to your constructor or to create a new Node object.
this->children = &children;
This doesn't make any sense since this->children is a vector of Node* and the children parameter is a vector of Node. Again, you'll need to either pass a vector of Node* to your constructor or to create new node objects.
You have the same issues in SetChildren and AddChildren.
Also, since you're manipulating your nodes as pointers, be very careful about the memory management. There's no garbage collector in C++, you'll have to delete every thing you new and at the proper time.

Check if below code helps you to create n-array tree creation.
struct TreeNode
{
vector<TreeNode*> children;
char value;
};
class TreeDictionary
{
TreeNode *root;
public:
TreeDictionary()
{
root = new TreeNode();
root->value = 0;
}
TreeNode *CreateNode(char data)
{
TreeNode *parent_node = new TreeNode;
if (parent_node)
parent_node->value = data;
return parent_node;
}
TreeNode* SearchElement(TreeNode *NextNode, char *data, int& val)
{
bool bVal = false;
for (vector<TreeNode*>::iterator it = NextNode->children.begin(); it != NextNode->children.end(); it++)
{
if ((*it)->value == *(data))
return SearchElement((*it), ++data, ++val);
}
return NextNode;
}
TreeNode *InsertNode(TreeNode *parent, TreeNode *ChildNode, char data)
{
if (parent == NULL)
ChildNode = CreateNode(data);
else
{
TreeNode *childNode = CreateNode(data);
parent->children.push_back(childNode);
return childNode;
}
return ChildNode;
}
void InsertMyString(string str)
{
TreeNode *NextNode = root;
for (int i = 0; i < str.size(); i++)
{
if (str[i] == '\0')
return;
cout << str[i] << endl;
if (NextNode->value == 0)
{
NextNode->value = str[i];
continue;
}
else if (NextNode->value != str[i])
{
NextNode = InsertNode(NextNode, NULL, str[i]);
}
else
{
TreeNode *node;
node = SearchElement(NextNode, &str[++i], i);
NextNode = InsertNode(node, NULL, str[i]);
}
}
}
};
int main()
{
TreeDictionary td;
td.InsertMyString("Monster");
td.InsertMyString("Maid");
td.InsertMyString("Monday");
td.InsertMyString("Malli");
td.InsertMyString("Moid");
return 0;
}

This implementation of SearchElement (without recursion) also works:
TreeNode* SearchElement(TreeNode *NextNode, char *data, int& val)
{
bool bVal = false;
for (vector<TreeNode*>::iterator it = NextNode->children.begin(); it != NextNode->children.end(); it++)
{
if ((*it)->value == *(data))
return (*it);
}
return NextNode;
}
TreeNode* res = SearchElement(root, data, value);
I checked this out, not understandable, why - it works for any node you want to find in the tree, no matter the depth and the level of the node in the tree, And that's unclear why, Because the loop iterates only over the children at the second level of the tree (children of the root node), Despite this - it even will find nodes with depth of 10 levels in the tree.

Related

linked list hash table with Segmentation fault

I'm trying to implement a hash table with a linked list, but it keeps giving me a Segmentation fault. I'm not sure where I did wrong. Basically, I create a dynamic array with Node, then I use each Node as the head of the linked list. I'm struggling with this for a few days. Just couldn't figure out where it's wrong. Can anyone help, please? Here's a simple version code.
#include<iostream>
#include<string>
class HashTable
{
public:
HashTable()
: hashMap{ new Node[10] }
{
for (int i = 0; i < 10; i++)
{
hashMap[i].next = nullptr;
}
}
~HashTable()
{
delete[] hashMap;
}
unsigned int hasher(const std::string& x)
{
return x[0]%10;
}
void add(const std::string& key)
{
Node* newNode = new Node;
newNode->key = key;
newNode->next = nullptr;
if (hashMap[hasher(key)].next==nullptr)
{
hashMap[hasher(key)].next = newNode;
}
else
{
Node* current = hashMap[hasher(key)].next;
while (current->next != nullptr)
{
current = current->next;
}
current->next = newNode;
}
delete newNode;
}
void print(std::string key)
{
std::cout<<hashMap[hasher(key)].next->key<<std::endl;
}
private:
struct Node
{
std::string key;
Node* next;
};
Node* hashMap;
};
int main()
{
HashTable ht;
ht.add("Hello");
ht.print("Hello");
}

How to call a function method recursively in classes in c++?

So, I started learning and reading about OOP not so long ago, I've been implementing all the data structures I know using classes and objects just for overall practice and to get comfortable with using OOP in c++.
I'm implementing the tree data structure and I've been wondering how to call a method recursively(I'm aware that I have to pass in an argument) so that when I create an object in main and call a specific method it's written like the following a.inorder(); and not a.inorder(root) since root is a private attribute.
Is this possible ?
My code:
#include<iostream>
using namespace std;
struct node
{
int data;
node* left;
node* right;
};
class tree
{
private:
node* root;
public:
tree();
tree(int val);
void insert(int val);
void preorder();
void postorder();
void inorder();
int count();
};
tree::tree() : root { NULL }
{
}
tree::tree(int val)
{
root = new node;
root->data = val;
root->left = root->right = NULL;
}
void tree::insert(int val)
{
if (!root)
{
root = new node;
root->data = val;
root->left = root->right = NULL;
}
else
{
node* t = root;
node* p = NULL;
while (t)
{
p = t;
if (val > root->data)
t = root->right;
else
t = root->left;
}
t = new node;
t->data = val;
t->left = t->right = NULL;
if (p->data > t->data)
p->left = t;
else
p->right = t;
}
}
void tree::preorder()
{
if (root)
{
}
}
In your design, a node refers to itself. Since it is the node object that is recursive, you could define the recursive method on node:
struct node
{
int data;
node* left;
node* right;
void preorder() {
//...
left->preorder();
right->preorder();
}
};
And then, tree::preorder() would just dispatch a call to root->preorder().
Write a private static recursive function passing to it the pointer to the root node and call the function from the corresponding public non-static member function.
For example
public:
std::ostream & preorder( std::ostream &os = std::cout ) const
{
return preorder( root, os );
}
//...
private:
static std::ostream & preorder( const node *root, std::ostream &os );
//...
This is a comment rather than an actual answer, as it addresses a different issue than you are asking about. However, it is too long for a comment space, that's why I post it here.
I suppose you erroneously refer to root in this part
while (t)
{
p = t;
if (val > root->data)
t = root->right;
else
t = root->left;
}
IMHO it should look like this:
while (t)
{
p = t;
if (val > t->data)
t = t->right;
else
t = t->left;
}
Also compare the code to seek a place for insert with a code that makes an actual insertion:
if (p->data > t->data)
p->left = t;
else
p->right = t;
You've put a comparison subexpressions in reversed order - when seeking, you test whether the new value is greater than that in an existing node, but when inserting, you test whether the existing value is greater than the new one. If they differ, the code will work OK, because you also swapped left and right in the 'then' and 'else' branch.
However, if the values appear equal, the execution control will go to 'else' in both places. As a result the testing code may stop at empty left pointer, but then a new node would get appended to the right, which was not tested for being NULL.
Why would the tree class do intrinsic operations on node? The node class knows best the node's internal structure, so let it initialize itself. This will also help you to stick to the DRY principle and, indirectly, to the KISS principle, as well as the Single-responsibility principle.
struct node
{
int data;
node* left;
node* right;
node(int val) : data(val), left(NULL), right(NULL) {}
};
class tree
{
private:
node* root;
public:
tree();
tree(int val);
void insert(int val);
};
tree::tree() : root { NULL }
{
}
tree::tree(int val) : root(new node(val))
{
}
void tree::insert(int val)
{
if (!root)
{
root = new node(val);
}
else
{
node* t = root;
node* p = NULL;
while (t)
{
p = t;
if (val < t->data)
t = t->left;
else
t = t->right;
}
t = new node(val);
if (t->data < p->data)
p->left = t;
else
p->right = t;
}
}
Additionally, you can make insert recursive, too.
struct node
{
int data;
node* left;
node* right;
node(int val) : data(val), left(NULL), right(NULL) {}
};
class tree
{
private:
node* root;
public:
tree();
tree(int val);
void insert(int val);
protected:
void insertat(node* p, int val);
};
void tree::insert(int val)
{
if (!root)
root = new node(val);
else
insertat(root, val);
}
void tree::insertat(node* t, int val);
{
if (val < t->data)
{
if (t->left)
insertat(t->left, val);
else
t->left = new node(val);
}
else
{
if (t->right)
insertat(t->right, val);
else
t->right = new node(val);
}
}

can not access memory at address 0xc8

I am writing a code to return data of a node in BST based on id.
below is my node class:
struct Node{
int id;
string data;
Node *left;
Node *right;
Node();
};
below is my node constructor: I defined id and data in addNode function
Node :: Node(){
this->left = nullptr;
this->right = nullptr;
}
below is my BST class:
class BST{
private:
Node * root = nullptr;
void setRoot(Node *);
Node* getRoot();
public:
Node *addNode(BST *, int);//helper function
Node *addNode(Node *,int);
string getEntry(BST*,int);//helper function
string getEntry(Node*,int);
}
below is my helper functions:
Node *BST::addNode(BST *bst, int val){
addNode(bst->getRoot(),val);
}
string BST::getEntry(BST* bst,int id){
getEntry(bst->getRoot(),id);
}
below is my addNode class:
Node* BST::addNode(Node* root, int val) {
Node *newNode = new Node();
newNode->id = val;
newNode->data = "Number " + to_string(val);
if (root == nullptr) {
if (getRoot() == nullptr){
setRoot(newNode);
}
setCount(getCount()+1);
return newNode;
}
if (root->id > val) {
root->left = addNode(root->left, val);
} else {
root->right = addNode(root->right, val);
}
return root;
}
below is my getEntry class:
string BST::getEntry(Node *base,int id) {
if (base == nullptr){
return "";
}
if (base->id == id){
cout<<base->data<<endl;
return base->data;
}
getEntry(base->left,id);
getEntry(base->right,id);
}
below are the nodes I passed in from main:
int main(){
BST *newBst = new BST();
newBst->addNode(newBst,1);
newBst->addNode(newBst,2);
newBst->addNode(newBst,3);
newBst->addNode(newBst,2);
newBst->addNode(newBst,3);
newBst->addNode(newBst,5);
newBst->addNode(newBst,7);
newBst->addNode(newBst,10);
cout<<newBst->getEntry(newBst,5)<<endl;
return 0;
}
The code would compile but does not return anything, I tried to debug, at the "return base->data statement", there is an error "can not access memory at address 0xc8". What causes the problem and what can I do about it?
this is the warning I got when I debug the code.
if (base->id != id){
getEntry(base->left,id);
getEntry(base->right,id);
}
As you are using a sorted tree, you know which of the right or left node you need to have a look at. Also, you need to return something:
if (base->id > val){
return getEntry(base->left,id);
}
return getEntry(base->right,id);
But the design with addNode is very bad, you shouldn't have to pass the root twice!

Unable to change the pointer value in class

I am trying to build a BST in C++, the root node inside class was not affecting when in call insert() function, it remains NULL.
I am passing root to insert_tree() function when I need to insert data into the tree but when I try to print root value inside insert_tree it always returning NULL
#include <iostream>
struct node
{
int value;
node *left;
node *right;
};
class bst
{
private:
node *root;
node* insert(node* parent,int value)
{
if(parent== NULL){
parent = new node;
parent->value = value;
parent->left = parent->right = NULL;
}
else if(parent->value>value){
parent->left = insert(parent->left,value);
}
else{
parent->right=insert(parent->right,value);
}
return parent;
}
void display(node* parent){
if(parent != NULL){
display(parent->left);
std::cout << parent->value <<"\t";
display(parent->right);
}
}
public:
bst(){
root = NULL;
}
void insert(int value){
root = insert(root,value);
}
void display(){
display(root);
}
};
int main(int argc, char const *argv[])
{
bst b1;
b1.insert(10);
b1.insert(1);
b1.insert(11);
b1.insert(9);
b1.display();
return 0;
}
I would suggest you read about BST first here and learn how insertion is done in a BST. First of all the algorithm is wrong and secondly, use pass by reference in insert_tree() function instead of pass by value. As you are passing by value, so the value of root doesn't change.

Implementing a Tree in C++ with List Children

I am trying to create a very simple tree in C++ out of nodes that have a string of data and a list of nodes signifying their children. I've gotten most of the way there, but have run into an error in (edit) running my code. Everything breaks down when I try and add a child to a node, specifically at the line children.push_back(n);
//It sets up the specified tree in a manner appropriate to the exercise, and then
//traverses the tree to find the node named "FindMe".
#include<stdio.h>
#include<stdlib.h>
#include <string>
#include <iostream>
#include <list>
struct node//Our implementation of a node.
{
public:
std::string Name;
std::list<struct node *> children;
void NameSet(std::string n){
Name = n;
}
std::string NameGet(){
return Name;
}
void ChildrenSetter(struct node *n){
children.push_back(n);
}
std::list<struct node *> ChildrenGetter(){
return children;
}
};
// A utility function to create a new BST node
struct node *newNode(std::string item)
{
struct node *temp = (struct node *)malloc(sizeof(struct node));
temp->NameSet(item);
return temp;
}
bool find(struct node *root, std::string f)
{
if (root != NULL)
{
std::cout << (root->NameGet()) << std::endl;
if(root->NameGet().compare(f)==0){
return true;
}
else{
std::list<struct node *> children = root->ChildrenGetter();
std::list<struct node *>::iterator outputIt;
for(outputIt = children.begin(); outputIt != children.end(); outputIt++){
if(find(*outputIt, f)){
return true;
}
}
}
}
return false;
}
/* This function creates the root */
struct node* insert(struct node* node, std::string Name)
{
if (node == NULL) return newNode(Name);
return node;
}
/* This function adds a left child to the current node. */
struct node* insertc(struct node* node, std::string Name)
{
if (node == NULL) return node;
struct node* temp = newNode(Name);
node->ChildrenSetter(newNode(Name));
return temp;
}
int main() //Here we build our tree and then find the requested node.
{
struct node *root = NULL;
root = insert(root, "Start");
struct node *A1 = insertc(root,"A1");
struct node *A2 = insertc(root, "A2");
struct node *D1 = insertc(A1,"D1");
insertc(D1,"E1");
struct node *B1 = insertc(A2,"B1");
struct node *B2 = insertc(A2, "B2");
insertc(B1,"FindMe");
insertc(B2, "C1");
if(find(root, "FindMe")){
std::cout << "Requested node found" << std::endl;
}
else{
std::cout << "Unable to find the requested node." << std::endl;
}
return 0;
}
EDIT: I figured it out, I needed to use new instead of malloc. Many thanks to the people who answered here.
//This code was written by Donnelly Warren in response to a Garmin Coding exercise given
//as part of an application for a summer internship on 2/20/18
//It sets up the specified tree in a manner appropriate to the exercise, and then
//traverses the tree to find the node named "FindMe".
#include<stdio.h>
#include<stdlib.h>
#include <string>
#include <iostream>
#include <list>
struct node//Our implementation of a node.
{
public:
std::string Name;
std::list<struct node *> children;
void NameSet(std::string n){
Name = n;
}
std::string NameGet(){
return Name;
}
void ChildrenSetter(struct node *n){
children.push_back(n);
}
std::list<struct node *> ChildrenGetter(){
return children;
}
};
// A utility function to create a new BST node
struct node *newNode(std::string item)
{
struct node *temp = new struct node;
temp->NameSet(item);
return temp;
}
bool find(struct node *root, std::string f)
{
if (root != NULL)
{
std::cout << (root->NameGet()) << std::endl;
if(root->NameGet().compare(f)==0){
return true;
}
else{
std::list<struct node *> children = root->ChildrenGetter();
std::list<struct node *>::iterator outputIt;
for(outputIt = children.begin(); outputIt != children.end(); outputIt++){
if(find(*outputIt, f)){
return true;
}
}
}
}
return false;
}
/* This function creates the root */
struct node* insert(struct node* node, std::string Name)
{
if (node == NULL) return newNode(Name);
return node;
}
/* This function adds a child to the current node. */
struct node* insertc(struct node* node, std::string Name)
{
if (node == NULL) return node;
struct node* temp = newNode(Name);
node->ChildrenSetter(temp);
return temp;
}
void del(struct node* node){//This will delete our tree.
if(node != NULL){
std::list<struct node *> children = node->ChildrenGetter();
std::list<struct node *>::iterator outputIt;
for(outputIt = children.begin(); outputIt != children.end(); outputIt++){
del(*outputIt);
}
delete node;
}
}
int main() //Here we build our tree and then find the requested node.
{
struct node *root = NULL;
root = insert(root, "Start");
struct node *A1 = insertc(root,"A1");
struct node *A2 = insertc(root, "A2");
struct node *D1 = insertc(A1,"D1");
insertc(D1,"E1");
struct node *B1 = insertc(A2,"B1");
struct node *B2 = insertc(A2, "B2");
insertc(B1,"FindMe");
insertc(B2, "C1");
if(find(root, "FindMe")){
std::cout << "Requested node found" << std::endl;
}
else{
std::cout << "Unable to find the requested node." << std::endl;
}
del(root);
return 0;
}
The issue is that children is not defined in the function where you are trying to use it, you will also have to pass a reference/pointer of the variable of type node.