Implementing a Tree in C++ with List Children - c++

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.

Related

I read the input number with getchar(), why is the number reversed in the linked list?

I typed 1234, but the list has 4,3,2,1 in it. I suspect the problem is getchar() itself, or a function in the class, but I have no way to find out.
The link class is responsible for some linked list operations, such as deletion, insertion, etc., while the node class is responsible for creating and assigning nodes.
The createlist class is responsible for the creation of the linked list, which is the main source of the problem. I wrote the debug statement in it, so you can run it and see the results for yourself
using namespace std;
class Node
{
public:
int data;
Node *next;
Node()
{
next = nullptr;
}
Node(int data)
{
this->data = data;
}
Node(const Node &temp)
{
this->data = temp.data;
}
};
class Link
{
public:
Node *head;
int length = 0;
Link()
{
head = new Node();
}
~Link()
{
while (head != nullptr)
{
Node *p = head->next;
free(head);
head = p;
}
}
void insert(const Node &cache)
{
Node *temp = new Node(cache);
temp->next = head->next;
head->next = temp;
length++;
}
};
void Creatlist(Link &link)
{
char cache;
while (1)
{
cache = getchar();
if (cache == '\n')
break;
link.insert(Node(cache - '0'));
cout << cache << " ";
}
cout<<endl;
Node *p = link.head->next;
cout << "in the linklist:";
while (p != nullptr)
{
cout << p->data << " ";
p = p->next;
}
}
int main()
{
Link link;
cout<<"inut numbers:"<<endl;
Creatlist(link);
}```
With the insert you inserted to the FRONT of the list. So you had "1", then "2->1" ... If you want to insert to the end, don't insert at the head, but hake a Node* tail in the class Link and an insert_end function as
//...
Node* temp;
void insert_end(const Node &cache){
Node *temp = new Node(cache);
tail->next=temp;
tail=tail->next;
length++;
}
Alsoin the constructor set tail=head

How to get below linked list with friend operator to working?

I am trying to execute linked list with the below code.But I am unable to figure out the mistake in it.
I got the concept of it but I am failing to implement the same.
Any help is highly appreciated.
#include <iostream>
using namespace std;
struct Node {
int data;
Node *next;
Node(int j) : data(j), next(nullptr) {}
friend ostream &operator<<(ostream &os, const Node &n) {
cout << "Node\n"
<< "\tdata: " << n.data << "\n";
return os;
}
};
void addElement(Node **head, int data){
Node *temp = nullptr;
temp->data = data;
temp->next=nullptr;
Node *cur = *head;
while(cur) {
if(cur->next == nullptr) {
cur->next = temp;
return;
}
cur = cur->next;
}
};
void printList(const Node *head){
const Node *list = head;
while(list) {
cout << list;
list = list->next;
}
cout << endl;
cout << endl;
};
void deleteList(Node *head){
Node *delNode =nullptr;
while(head) {
delNode = head;
head = delNode->next;
delete delNode;
}};
int main() {
Node *list = nullptr;
addElement(&list, 1);
addElement(&list, 2);
printList(list);
deleteList(list);
return 0;
}
after compiling I am getting no error and no output.So I am unable to figure what is going wrong or else my implementation of which is not right!
Here an error straightaway
void addElement(Node **head, int data){
Node *temp = nullptr;
temp->data = data;
temp is null, but you dereference it. It's an error to dereference a null pointer.
I guess you meant this
void addElement(Node **head, int data) {
Node *temp = new Node(data);
which allocates a new Node, initialises it with data and makes temp point to the newly allocated Node.

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!

Creating a n-ary tree

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.

C++ Linked List Runtime Error: Unhandled Exception - Writing Location Violation

I am trying to build my own implementation of a linked list in C++. My code is compiling but apparently there is some issue with my pointers referring to invalid memory addresses.
Here is my implementation:
#include <iostream>
#include <string>
using namespace std;
class Node
{
private:
string _car;
Node* nextNode;
public:
void setCar(string car)
{
_car = car;
}
string getCar()
{
return _car;
}
void setNextNode(Node* node)
{
nextNode = node;
}
Node* getNextNode()
{
return nextNode;
}
};
Node* findLast(Node* node)
{
Node* nodeOut = NULL;
while (node->getNextNode() != NULL)
{
nodeOut = node->getNextNode();
}
return nodeOut;
}
string toString(Node* node)
{
string output = "";
while (node->getNextNode() != NULL)
{
output += node->getCar() + " ";
node = node->getNextNode();
}
return output;
}
int main()
{
char xit;
//ser head node to NULL
Node* headNode = NULL;
//create node 1
Node* node1 = new Node();
node1->setCar("Mercedes");
//create node 2
Node* node2 = new Node();
node2->setCar("BMW");
//set node links
headNode->setNextNode(node1);
node1->setNextNode(node1);
node2->setNextNode(node2);
headNode = node1;
Node* lastNode = findLast(headNode);
lastNode->setNextNode(NULL);
cout << toString(headNode) << endl;
//pause console
cin >> xit;
}
You need to relook at your code.
headNode = node1;
This assignment should be done before accesing any member function of the instance headNode.
Intially you have assigned NULL to this pointer.
After creating node1 you are setting to headNode that is invalid instance. This is the cause of crash.
Be ensure with your objective and then try to implement do some rough work on paper , make some diagram that way you would be more clear that what you are exactly trying to achive.
why setNextNode ??? i don't undeerstand what you wanted to achieve. be clear first.
As per my undertanding this code should be implemented like below..
#include <iostream>
#include <string>
using namespace std;
class Node
{
private:
string _car;
Node* nextNode;
public:
void setCar(string car)
{
_car = car;
}
string getCar()
{
return _car;
}
void setNextNode(Node* node)
{
nextNode = node;
}
Node* getNextNode()
{
return nextNode;
}
};
Node* findLast(Node* node)
{
Node* nodeOut = node->getNextNode();
while ( nodeOut->getNextNode()!= NULL)
{
nodeOut = nodeOut->getNextNode();
}
return nodeOut;
}
string toString(Node* node)
{
string output = "";
while (node != NULL)
{
output += node->getCar() + " ";
node = node->getNextNode();
}
return output;
}
int main()
{
char xit;
//ser head node to NULL
Node* headNode = NULL;
//create node 1
Node* node1 = new Node();
node1->setCar("Mercedes");
node1->setNextNode(NULL);//Make null to each next node pointer
headNode = node1; //assign the node1 as headNode
//create node 2
Node* node2 = new Node();
node2->setCar("BMW");
node2->setNextNode(NULL);
//set node links
node1->setNextNode(node2);
Node* lastNode = findLast(headNode);
lastNode->setNextNode(NULL);
cout << toString(headNode) << endl;
//pause console
cin >> xit;
}
Hope it would be useful for the beginner who implement ing the linklist in c++.
Reread this:
node1->setNextNode(node1);
node2->setNextNode(node2);
...and think about what you're doing here.
If you're going to write linked-list code, I'd advise at least looking at the interface for std::list. Right now, you're interface is at such a low level that you'd be at least as well off just manipulating pointers directly.
The cause of your actual error is:
headNode->setNextNode(node1);
headNode is still set to NULL, thus you're dereferencing a NULL pointer. As noted by Jerry, you're also calling having nodes point to themselves, which is not what you want.
It would be cleaner if you took the car as a constructor parameter.
When you allocate a new Node, the pointer nextNode is not initialized, it's just random junk. You will need to explicitly set it to NULL (probably in a constructor for Node).
Also, I assume you know that the standard C++ library has a linked list built in and you're just doing this for learning ;-)
Thanks for all the suggestions, here is my final code after major cleanup:
// LinkedListProject.cpp : main project file.
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace System;
using namespace std;
class Node
{
public:
Node()
:_car(""), _nextNode(NULL)
{
}
void SetCar(string car)
{
_car = car;
}
string GetCar()
{
return _car;
}
void SetNextNode(Node *node)
{
_nextNode = node;
}
Node * GetNextNode()
{
return _nextNode;
}
private:
string _car;
Node *_nextNode;
};
string GetData();
Node * AddNode(Node *firstNode, Node *newNode);
Node * DeleteNode(Node *firstNode, string nodeData);
void PrintNodes(Node *firstNode);
int main(int argc, char *argv[])
{
string command = "";
string data = "";
Node *firstNode = NULL;
do
{
cout << "Enter command: ";
cin >> command;
if(command == "add")
{
data = GetData();
Node *newNode = new Node();
newNode->SetCar(data);
firstNode = AddNode(firstNode, newNode);
}
else if(command == "delete")
{
data = GetData();
firstNode = DeleteNode(firstNode, data);
}
else if(command == "print")
{
PrintNodes(firstNode);
}
} while(command != "stop");
return 0;
}
string GetData()
{
string data = "";
cout << "Enter data: ";
cin >> data;
return data;
}
Node * AddNode(Node *firstNode, Node *newNode)
{
//add new node to front of queue
newNode->SetNextNode(firstNode);
firstNode = newNode;
return firstNode;
}
Node * DeleteNode(Node *firstNode, string nodeData)
{
Node *currentNode = firstNode;
Node *nodeToDelete = NULL;
if (firstNode != NULL)
{
//check first node
if(firstNode->GetCar() == nodeData)
{
nodeToDelete = firstNode;
firstNode = firstNode->GetNextNode();
}
else //check other nodes
{
while (currentNode->GetNextNode() != NULL &&
currentNode->GetNextNode()->GetCar() != nodeData)
{
currentNode = currentNode->GetNextNode();
}
if (currentNode->GetNextNode() != NULL &&
currentNode->GetNextNode()->GetCar() == nodeData)
{
nodeToDelete = currentNode->GetNextNode();
currentNode->SetNextNode(currentNode->GetNextNode()->GetNextNode());
}
}
if(nodeToDelete != NULL)
{
delete nodeToDelete;
}
}
return firstNode;
}
void PrintNodes(Node *firstNode)
{
Node *currentNode = firstNode;
while(currentNode != NULL)
{
cout << currentNode->GetCar() << endl;
currentNode = currentNode->GetNextNode();
}
}