create a BST of string . error - c++

Inserting just one node to the tree works fine, but on inserting the 2nd node onwards, the program crashes. Here is the code:
#include <iostream>
#include <cstring>
using namespace std;
struct node
{
char* key;
node *left, *right;
};
// A utility function to create a new BST node
node *newNode(const char* item)
{
node *temp =new node;
strcpy(temp->key,item);
temp->left = temp->right = NULL;
return temp;
}
// A utility function to do inorder traversal of BST
void inorder(node *root)
{
if (root!= NULL)
{
inorder(root->left);
cout<<root->key<<endl;
inorder(root->right);
}
}
/* A utility function to insert a new node with given key in BST */
node* insert(node* tnode,const char* key)
{
/* If the tree is empty, return a new node */
if (tnode == NULL)
return newNode(key);
/* Otherwise, recur down the tree */
if (strcmp(key,tnode->key) < 0)
tnode->left = insert(tnode->left, key);
else if (strcmp(key,tnode->key) > 0)
tnode->right = insert(tnode->right, key);
/* return the (unchanged) node pointer */
return tnode;
}
// Driver Program to test above functions*/
int main()
{
node *root = NULL;
char* word[]={"elephant","hi","little","nil",NULL};
root = insert(root,word[0]); //works fine
for(int i=1;word[i];i++)
insert(root,word[i]);
// print inoder traversal of the BST
inorder(root);
return 0;
}
after:
root = insert(root,word[0]);
inorder(root);
o/p: elephant
on inserting 2nd node
crashes

You're not initialising the key array that item will get copied into. Try this:
node *newNode(const char* item)
{
node *temp = new node();
temp->key = new char[strlen(item) + 1];
strcpy(temp->key,item);
temp->left = temp->right = NULL;
return temp;
}
That said, there are some more problems with your code, like no destructors etc. I'd strongly recommend reading some good books/tutorials on programming in C++.

Related

Try tree inplementation

Try to make tree , have a some troubles, first it's print function - it's print not integers that i put, but print random numbers;
Another trouble its append child - its works only one times;
Will be happy if you will help me with this task.
And also give some good articles about linked lists, trees on c and c++;
#include <iostream>
#include <stdio.h>
using namespace std;
struct Node
{
void* m_pPayload;
Node* m_pParent;
Node* m_Children;
};
struct Person
{
int m_Id;
};
//typedef bool (*NodeComparator)(void* pValue, void* pPayload);
/*bool Comp(void* pValue, void* pPayload)
{
Person* pVal = (Person*)pValue;
Person* pPay = (Person*)pPayload;
if (pVal->m_Id == pPay->m_Id)
return true;
else
return false;
}
*/
Node* NewNode(void* pPayload)
{
Node* pNode = new Node;
pNode->m_pParent = nullptr;
pNode->m_Children = 0;
pNode->m_pPayload = pPayload;
return pNode;
}
Person* NewPerson(int id)
{
Person* p = new Person;
p->m_Id = id;
return p;
}
//Node* FindNode(Node* pParent, Node* m_pPayload, NodeComparator comparator);
void AppendChild(Node* pParent, Node* pNode)
{
if (pParent->m_Children == NULL)
pParent->m_Children = pNode;
}
void print(Node* head)
{
Node* current_node = head;
while (current_node != NULL)
{
printf("%d\n ", current_node->m_pPayload);
current_node = current_node->m_Children;
}
}
int main()
{
Node* T = new Node;
T = NewNode(NewPerson(5));
AppendChild(T, NewNode(NewPerson(11)));
AppendChild(T, NewNode(NewPerson(15)));
print(T);
}
printf("%d\n ", current_node->m_pPayload)
is incorrect. %d wants an integer and it's being given a pointer. The results will be unusual, and likely appear to be random garbage.
printf("%d\n ", ((Person*)current_node->m_pPayload)->m_Id);
^ ^
| Get id from Person
treat payload pointer as pointer to Person
will solve the immediate problem.
Your code actually seems to be pretty messed up with a lot of things going on, here sharing my own commented code from few years back, hope it helps
#include <bits/stdc++.h>
using namespace std;
// Single node representation
struct node {
int data;
node *left, *right;
};
// Declaring temp for refference and root to hold root node
node *root, *temp;
// This function only generates a node and return it to the calling function with data stored in it
node* generateNode(int data){
temp = new node();
temp->data = data;
temp->left = temp->right = NULL;
return temp;
}
// This function actually adds node to the tree
node* addNode(int data, node *ptr = root){
// If the node passed as ptr is NULL
if(ptr == NULL){
ptr = generateNode(data);
return ptr;
}
// Condition to check in which side the data will fit in the tree
else if(ptr->data < data)
//if its in right, calling this function recursively, with the right part of the tree as the root tree
ptr->right = addNode(data, ptr->right);
else
//In case the data fits in left
ptr->left = addNode(data, ptr->left);
//Note: if there is no data in left or roght depending on the data's valid position, this function will get called with NULL as second argument and then the first condition will get triggered
//returning the tree after appending the child
return ptr;
}
//Driver function
int main ()
{
int c, data;
for (;;){
cin >> c;
switch(c){
case 1:
cout << "enter data: ";
cin >> data;
//Updating root as the tree returned by the addNode function after adding a node
root = addNode(data);
break;
default:
exit(0);
break;
}
}
return 0;
}
Please find below a piece of code that should easily get you started. It compiles and it traverse the tree using recursion.
#include <iostream>
#include <vector>
#include <stdio.h>
using namespace std;
struct Node
{
int m_Id;
vector<Node*> m_Children;
Node(const int& id){
m_Id = id;
}
void AppendChild(Node* pNode) {
m_Children.push_back(pNode);
}
void Print() {
printf("%d\n ", m_Id);
}
};
void traverse(Node* head)
{
Node* current_node = head;
current_node->Print();
for(int i = 0; i<current_node->m_Children.size(); i++) {
traverse(current_node->m_Children[i]);
}
}
int main()
{
Node* T0 = new Node(0);
Node* T10 = new Node(10);
T10->AppendChild(new Node(20));
Node* T11 = new Node(11);
Node* T12 = new Node(12);
Node* T22 = new Node(22);
T22->AppendChild(new Node(33));
T12->AppendChild(T22);
T0->AppendChild(T10);
T0->AppendChild(T11);
T0->AppendChild(T12);
traverse(T0);
}
First for printing the node value
Talking about the current mistake that you had committed is in the above code is:
You have not mentioned its pointer to its child (specifically right or left). Due to which it is showing garbage value every time.
For e.g.: print( node->left);
Since you need to type caste it properly to show the data of data.
For e.g.: printf("%d\n ", ((Person*)current_node->m_pPayload)->m_Id);
There is a specific direction in which you want to print data. For trees, there are three directions in which you can print the data of the node and they are as follow:
Left order or Inorder traversal
Preorder traversal
Postorder traversal
This can give you better information about traversal.
Secondly for adding the node to a tree
This might help explain it better.

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!

Binary search tree Inorder tranversal recursive function doesn't work correctly

I am trying to create a binary search tree in C++ with struct. In this code the 'inorder' function doesn't work. My code is below:
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
struct node{
struct node *left, *right,*root;
int data,count;
}*new_node,*tree, *temp,*ruff;
void root_create(){
tree = (struct node *)malloc(sizeof(struct node));
tree->root = NULL;
tree->count=0;
}
void node_create(int data){
new_node = (struct node *)malloc(sizeof(struct node));
new_node->data = data;
new_node->left=NULL;
new_node->right=NULL;
}
node * node_insert(node *tree){
temp = tree->root;
if(temp==NULL){
temp = new_node;
temp->count++;
return temp;
}
else if(temp->left==NULL and temp->right==NULL){
if(temp->data > new_node->data){
tree->root->left = new_node;
}
else if(tree->root->data <= new_node->data){
tree->root->right = new_node;
}
temp->count++;
return temp;
}
else{
if(temp->data <= new_node->data){
return node_insert(temp->right);
}
if(temp->data > new_node->data){
return node_insert(temp->left);
}
}
}
void inorder(node *){
if(ruff == NULL){
cout<<"No Data!"<<endl;
return;
}
if(ruff->left!=NULL){
inorder(ruff->left);
}
cout<< ruff->data<<endl;
if(ruff->right!=NULL){
inorder(ruff->right);
}
cout<< ruff->data<<endl;
}
int main()
{
int data=321;
root_create();
node_create(data);
tree->root = node_insert(tree);
data=123;
node_create(data);
tree->root = node_insert(tree);
ruff = tree->root;
inorder(tree);
return 0;
}
In main function I've created two node and attached them to tree->root. I can access the data from tree->root. But when I call inorder function, it doesn;t show any output.
You're using the static variable "ruff" in your inorder function, rather than the passed parameter, which you've neglected to give a name to.
When you've got it working, the inorder() function is very simple:
First you call inorder() on the left pointer of the current node.
Then, you print the value of the current node.
Finally, you call inorder() on the left pointer of the current node.
In order for the recursion to end, you need to exit early from inorder() if the passed-in node* is NULL.

Inserting a node into a binary search tree in C++

I'm attempting to build a binary search tree and then do a horizontal inorder print with the left most node as the first node displayed. Also, preceding each node is its depth (distance from root) as well as a tilde to help visualize the tree itself. Conceptually my code seems to be correct, but for whatever reason I can't seem to get it to build the tree properly. I figure that the error is most likely in my insert function, but I can't seem to locate it.
Any suggestions or ideas would be extremely helpful!
#include <iostream>
#include <cstdlib>
#include <fstream>
#include <iomanip>
#include <algorithm>
using namespace std;
typedef struct treeNode {
treeNode *leftChild;
treeNode *rightChild;
int data;
} treeNode;
void printTree(treeNode*);
int getNodeDepth(treeNode*);
treeNode* insert(treeNode*, int);
treeNode* createNewNode(int);
int main()
{
//read in file here
treeNode *root = NULL;
root = insert(root, 8);
root = insert(root, 1);
root = insert(root, 90);
root = insert(root, 3);
root = insert(root, 80);
root = insert(root, 6);
root = insert(root, 83);
printTree(root);
return 0;
}
/*
Purpose: Constructs a new node for the tree.
Inputs: The data for the node.
Outputs: returns the new node
*/
treeNode* createNewNode(int data)
{
treeNode *newNode = new treeNode;
newNode->data = data;
newNode->leftChild = NULL;
newNode->rightChild = NULL;
return newNode;
}
/*
Purpose: Calculates the depth of a given node using recursion.
Inputs: The node to check the depth on.
Outputs: returns the depth
*/
int getNodeDepth(treeNode *node)
{
if (node == NULL) // tree doesn't exist
return(0);
return(1 + max(getNodeDepth(node->leftChild), getNodeDepth(node->rightChild)));
}
/*
Purpose: Inserts a node into the tree.
Inputs: The node to be inserted and the data for the node.
Outputs: returns the inserted node
*/
treeNode* insert(treeNode *node, int data)
{
if (node == NULL)
return createNewNode(data);
else
{
if (data <= node->data)
{
node->leftChild = insert(node->leftChild, data);
}
else
{
node->rightChild = insert(node->rightChild, data);
}
return node;
}
}
/*
Purpose: Prints the BST in a horizontal inorder format.
Inputs: The root node.
Outputs: nothing
*/
void printTree(treeNode *node)
{
if (node == NULL)
return;
printTree(node->leftChild);
cout << "(" << (getNodeDepth(node)-1) << ") ";
for (int i=0; i<(getNodeDepth(node)-1); i++)
cout << "~";
cout << node->data << endl;
printTree(node->rightChild);
}
The current output is as follows:
(2) ~~1
(1) ~3
(0) 6
(3) ~~~8
(1) ~80
(0) 83
(2) ~~90
Obviously it can't have two roots (ie 6 and 83). Thanks!
For those in the future who wish for a correct implementation of the answer to my original question here is the refactored code that I came up. I decided to take an OOP approach and modified the insert and getNodeDepth function to appropriately work.
//
// Binary Search Tree
//
#include <iostream>
#include <cstdlib>
#include <fstream>
#include <iomanip>
#include <algorithm>
using namespace std;
// binary search tree
class BST {
private:
typedef struct treeNode {
treeNode *leftChild;
treeNode *rightChild;
int data;
} treeNode;
treeNode *root;
public:
//Constructor
BST() { root = NULL; }
/*
Purpose: Constructs a new node for the tree.
Inputs: The data for the node.
Outputs: returns the new node
*/
treeNode* createNewNode(int data)
{
treeNode *newNode = new treeNode;
newNode->data = data;
newNode->leftChild = NULL;
newNode->rightChild = NULL;
return newNode;
}
//Check if the tree is empty
bool isEmpty() const { return root==NULL; }
/*
Purpose: Calculates the depth of a given node using recursion.
Inputs: The node to check the depth on and the node to check the depth from.
Outputs: returns the depth
*/
int getNodeDepth(treeNode *node, treeNode *from)
{
if (node == from)
return 0;
else if (node->data < from->data)
return getNodeDepth(node, from->leftChild) + 1;
else
return getNodeDepth(node, from->rightChild) + 1;
}
/*
Purpose: Inserts a node into the tree.
Inputs: The data for the node.
Outputs: none
*/
void insert(int newData)
{
treeNode* t = createNewNode(newData);
treeNode* parent;
parent = NULL;
if(isEmpty()) //check if tree exists or not
root = t;
else {
//Note: ALL insertions are as leaf nodes
treeNode* curr;
curr = root;
// Find the Node's parent
while(curr)
{
parent = curr;
if (t->data > curr->data)
curr = curr->rightChild;
else
curr = curr->leftChild;
}
if ((t->data) < (parent->data))
parent->leftChild = t;
else
parent->rightChild = t;
}
}
/*
Purpose: Prints the BST in a horizontal inorder format.
Inputs: The root node.
Outputs: nothing
*/
void printTree(treeNode *node)
{
if (node == NULL)
return;
printTree(node->leftChild);
cout << "(" << getNodeDepth(node, root) << ") ";
for (int i=0; i<getNodeDepth(node, root); i++)
cout << "~";
cout << node->data << endl;
printTree(node->rightChild);
}
//Getter for private member variable root
void printInorder()
{
printTree(root);
}
};
int main()
{
// read file in here
BST temp;
temp.insert(8);
temp.insert(1);
temp.insert(90);
temp.insert(3);
temp.insert(80);
temp.insert(6);
temp.insert(83);
temp.printInorder();
return 0;
}
The correct output looks as follows with 8 as the root:
(1) ~1
(2) ~~3
(3) ~~~6
(0) 8
(2) ~~80
(3) ~~~83
(1) ~90
Hope this helps!
In the first you shouldn't write treeNode twice
typedef struct {
treeNode *leftChild;
treeNode *rightChild;
int data;
} treeNode;
In the second you create a memory leak:
treeNode *root = new treeNode;
root = NULL;
You should write:
treeNode *root = NULL;
Obviously it can't have two roots (ie 6 and 83). Thanks!
6 and 83 aren't roots. 8 is a root. So your program gave right answer.

Dummy Head Node Linked List

I'm trying to write an insert function for string values for a circular doubly linked list. I saw that creating a dummy node is beneficial in doing this so I can eliminate special cases like when the list is empty. The problem is I'm not finding alot of good information on dummy head nodes. I understand their purpose, but I don't understand how I create/implement it.
appreciate all the code examples guys, tried to figure it out on my own getting a little stuck though if someone can look at it.
#include <iostream>
#include <string>
using namespace std;
typedef string ListItemType;
struct node {
node * next;
node * prev;
ListItemType value;
};
node * head;
node * dummyHead = new node;
void insert(const ListItemType input, node * & within);
void main(){
insert("bob",dummyHead);
}
void insert( const ListItemType input, node * &ListHead){
node *newPtr = new node;
node *curr;
newPtr->value = input;
curr = ListHead->next; //point to first node;
while (curr != ListHead && input < curr->value){
curr = curr->next;
}
//insert the new node pointed to by the newPTr before
// the node pointed to by curr
newPtr->next = curr;
newPtr->prev = curr->prev;
curr->prev = newPtr;
newPtr->prev->next = newPtr;
}
For a circular doubly linked list, you can setup 1 sentinel node where both "next" and "prev" points to itself when list is empty. When list is not empty, sentinel->next points to first element and sentinel->prev points to last element. With this knowledge, your insert and remove function would look something like this.
This is very basic and your LinkedList and Node class maybe implemented differently. That is OK. The main thing is the insert() and remove() function implementation that shows how sentinel node(s) removes the need for checking for NULL values.
Hope this helps.
class DoublyLinkedList
{
Node *sentinel;
int size = 0;
public DoublyLinkedList() {
sentinel = new Node(null);
}
// Insert to the end of the list
public void insert(Node *node) {
// being the last node, point next to sentinel
node->next = sentinel;
// previous would be whatever sentinel->prev is pointing previously
node->prev = sentinel->prev;
// setup previous node->next to point to newly inserted node
node->prev->next = node;
// sentinel previous points to new current last node
sentinel->prev = node;
size++;
}
public Node* remove(int index) {
if(index<0 || index>=size) throw new NoSuchElementException();
Node *retval = sentinel->next;
while(index!=0) {
retval=retval->next;
index--;
}
retval->prev->next = retval->next;
retval->next->prev = retval->prev;
size--;
return retval;
}
}
class Node
{
friend class DoublyLinkedList;
string *value;
Node *next;
Node *prev;
public Node(string *value) {
this->value = value;
next = this;
prev = this;
}
public string* value() { return value; }
}
Why are you trying to use dummy node?
I hope you can handle it without a dummy node.
Eg:
void AddNode(Node node)
{
if(ptrHead == NULL)
{
ptrHead = node;
}else
{
Node* itr = ptrHead;
for(int i=1; i<listSize; i++)
{
itr = itr->next;
}
itr->next = node;
}
listSize++;
}
The above one is an example to handle the linked list without dummy node.
For a circular double linked list without a dummy node, the first node previous pointer points to the last node, and the last node next pointer points to the first node. The list itself has a head pointer to first node and optionally a tail pointer to last node and/or a count.
With a dummy node, the first node previous pointer points to the dummy node and the last node next pointer points to the dummy node. The dummy nodes pointers can point to the dummy node itself or be null.
The HP / Microsoft STL list function uses a dummy node as a list head node with the next pointer used as a head pointer to the first real node, and the previous pointer used as a tail pointer to the last real node.
#include <iostream>
#include <string>
using namespace std;
typedef string ElementType;
struct Node
{
Node(){}
Node(ElementType element, Node* prev = NULL, Node* next = NULL):element(element){}
ElementType element;
Node* prev;
Node* next;
};
class LinkList
{
public:
LinkList()
{
head = tail = dummyHead = new Node("Dummy Head", NULL, NULL);
dummyHead->next = dummyHead;
dummyHead->prev = dummyHead;
numberOfElement = 0;
}
void insert(ElementType element)
{
Node* temp = new Node(element, NULL, NULL);
if (0 == numberOfElement)
{
head = tail = temp;
head->prev = dummyHead;
dummyHead->next = head;
tail->next = dummyHead;
dummyHead->prev = tail;
}
else
{
tail->next = temp;
temp->prev = dummyHead->next;
temp->next = dummyHead;
dummyHead->next = temp;
tail = temp;
}
numberOfElement += 1;
}
int length() const { return numberOfElement; }
bool empty() const { return head == dummyHead; }
friend ostream& operator<< (ostream& out, const LinkList& List);
private:
Node* head;
Node* tail;
Node* dummyHead;
int numberOfElement;
};
ostream& operator<< (ostream& out, const LinkList& List)
{
Node* current = List.head;
while (current != List.dummyHead)
{
out<<current->element<<" ";
current = current->next;
}
out<<endl;
return out;
}
int main()
{
string arr[] = {"one", "two", "three", "four", "five"};
LinkList list;
int len = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < len; ++i)
{
list.insert(arr[i]);
}
cout<<list<<endl;
}
I think this code can help you. When you want to implement some data structure, you must have a clear blueprint about it.
Do the following inside the constructor
ptrHead = new Node();
listSize = 1;
if you have tail also,
ptrHead->next = ptrTail;
The above code will create dummy node.
Make sure you implementation should not affected by this dummy node.
eg:
int getSize()
{
return listSize-1;
}