Breadth First Search on a Binary tree - c++

I'm trying to traverse on a binary tree to find someone's ID by using his/her ID number. When I debug this function it works well, but on the other hand, when I directly run, it terminates itself.. Can someone figure it out please?
struct person{
char ID[15];
char name[30] ;
char surname[30];
person *left;
person *right;
};
struct tree{
person *root;
void bfsSearch();
void BFS(person*,char*);
};
void tree::BFS(person *root,char *search)
//BFS traversal on a binary tree
{
char *temp;
std::deque<person *> q;
q.push_back(root);
temp=strncpy(temp,q.front()->ID,8);
while (q.size() != 0)
{
person *next = q.front();
if (strcmp(search,temp)==0)
{
cout<<"Result: "<<q.front()->ID<<endl;
break;
}
q.pop_front();
if (next->left)
q.push_back(next->sol);
if (next->right)
q.push_back(next->sag);
temp=strncpy(temp,q.front()->ID,8);
}
}
void tree::bfsSearch()
{
person *scan;
char *data,*temp;
data=new char[15];
scan=root;
cout<<"Enter the Person`s ID to search: ";cin>>data;
BFS(root,data);
}

char *temp;
temp=strncpy(temp,q.front()->ID,8);
You are copying data into an uninitialized pointer, which is undefined behavior. You need to declare temp as an array, or allocate it dynamically. Since you are only copying up to 8 bytes, using char temp[9]; should be enough. Note though that strncpy will leave the string unterminated if the input was too long, so you'd need to add temp[8]=0; to be safe.
There is also no point in assigning the result of strncpy back to temp, since it just returns its first argument.
It's much better to do things the C++ way: Use std::string and avoid all this messing around with char pointers and null-terminators.

Related

c++ Unable to initialize array of pointers to null c++

I am trying to create a trie, but when I initialize the pointers in the array to NULL it breaks the program. The program finishes but won't output anything. Why is it doing this I look at online examples and they are doing it.
class trie
{
private:
struct Node
{
char letter;
Node *children[26];
};
//the beginning of the trie
Node *root;
public:
/* Constructors with No Arguments */
trie(void);
/* Destructor */
~trie(void);
//Function to insert string into the trie.
void insert(string word);
//Function to help insert
void insertHelper(string word, Node * & trieNode);
//Funtion to print the contents of the trie.
void printTrie();
//Function to get the index if a char matches.
int getIndex(char letter);
};
trie::trie()
{
/* Initialize the root of the node */
root = NULL;
for(int i = 0; i < 26; i++){
root->children[i] = NULL;
}
}
trie::trie()
{
root = NULL;
for(int i = 0; i < 26; i++){
root->children[i] = NULL; // you are following the nullptr
}
}
In modern C++ you should use nullptr instead of NULL. No, in fact you should be using smart pointers like std::shared_ptr<> and std::unique_ptr<> or std::vector<>.
I suggest you read #2 of the Ten Commandments for C Programmers
:
2: Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.
Clearly the holy scriptures were mis-transcribed here, as the words should have been ``null pointer'', to minimize confusion between the concept of null pointers and the macro NULL (of which more anon). Otherwise, the meaning is plain. A null pointer points to regions filled with dragons, demons, core dumps, and numberless other foul creatures, all of which delight in frolicing in thy program if thou disturb their sleep. A null pointer doth not point to a 0 of any type, despite some blasphemous old code which impiously assumes this.
"Following the NULL pointer" here means to dereference it.

Data Structure in C++. insertion in the beginning of the node in linked list

I am learning data structures in C++. This is a simple program for insertion
using links and nodes. The insertion takes place at the beginning of the node.
I do not understand some parts of the code.
In the function display() the pointer np points to the inserted info and then takes the value of the previous info using the next node. The next pointer is pointing to the previous info using the insert_beginning() function.
Displaying is done using the while loop. How does the next pointer change its value during each loop?
PS: The program runs fine.
#include<iostream>
#include<process.h>
#include<cstdlib>
using namespace std;
struct node
{
int info;
node *next;
}*start,*newptr,*save,*ptr;
node *create_new_node(int);
void insert_beg(node*);
void display(node*);
/*----------------------------------------------------------------------------------------------------------------------------
The pointer 'start' points to the beginning of the list.
Function 'create_new_node()' takes one integer argument , allocates memory to create new node and returns
the pointer to the new node.(return type: node*)
Function 'insert_beg()' takes node* type pointer as an argument and inserts this node in the beginning of the list.
Function display takes node* type pointer as an argument and displays the list from this pointer till the end of the list
------------------------------------------------------------------------------------------------------------------------------
*/
int main()
{
start=NULL;
int inf;
char ch='y';
while(ch=='y'||ch=='Y')
{
system("cls");
cout<<"enter information for the new node ";
cin>>inf;
cout<<"\ncreating new node. Press enter to continue ";
system("pause");
newptr = create_new_node(inf);
if(newptr!=NULL)
{
cout<<"\nnew node created successfully. Press enter to
continue. ";
system("pause");
}
else
{
cout<<"\nCannot create new node. ABORTING!! ";
exit(1);
}
cout<<"\nnow inserting this node in the beginning of the list.
Press enter to continue ";
system("pause");
insert_beg(newptr);
cout<<"\nNow the list is \n";
display(start);
cout<<"\nPress 'Y' to enter more nodes, 'N' to exit\n";
cin>>ch;
}
return 0;
}
node *create_new_node(int n)
{
ptr=new node;
ptr->info=n;
ptr->next=NULL;
}
void insert_beg(node *np)
{
if(start==NULL)
start=np;
else
{
save=start;
start=np;
np->next=save;
}
}
void display(node *np)
{
while(np!=NULL)
{
cout<<np->info<<" ->";
np=np->next;
}
cout<<"!!!\n";
}
To cut the long story short - per my understanding, your basic question is:-
display is done using the while loop. how does the next pointer change
its value during each loop??
This happens precisely in this line:-
np=np->next;
You are basically advancing the pointer to the node structure to another node structure whose address is in next member of the first node structure. This is text book stuff and any basic algo book should cover this thoroughly
HTH!
Your question is somewhat unclear. Especially because you state that:
PS:the program runs fine.
which it for sure does not. There is a bug that simply means this program will not work.
The problem is that create_new_node is not returning the pointer value
node *create_new_node(int n)
{
ptr=new node;
ptr->info=n;
ptr->next=NULL;
return ptr; // This line is missing
}
Besides that it is a really bad idea to use global pointer variables!
Here
struct node
{
int info;
node *next;
}*start,*newptr,*save,*ptr;
you define the struct node but you also define 4 variables, i.e. 4 pointers to node. These variables will be global, i.e. available in all your code. Something that you should never do.
Instead make local variables as needed - for instance:
node *create_new_node(int n)
{
node *ptr; // Local variable instead of global
ptr=new node;
ptr->info=n;
ptr->next=NULL;
return ptr;
}
Then for the insert_beg change it so that it returns a new start pointer - like:
node* insert_beg(node* start, node *np)
{
np->next=start;
return np;
}
and use it in main like:
node* start = NULL;
...
...
start = insert_beg(start, newptr);
BTW - In modern C++ you would never use raw pointers and you would never write your own list. Use smart pointers instead of raw pointer. Use the standard containers instead of writing your own.

What causes run time error in the following program?

I am using this simple function to create a new node
node* Tree::createNewNode(int score, const char* word)
{
// Create a new node with the information available
node* n = new node;
n->left=NULL;
n->right = NULL;
n->parent = NULL;
n->score = score;
strcpy(n->word,word);
return n;
}
node is a structure:
struct node
{
int score; // the score or label of the node
char *word; // the word stored in the node
node *left; // the pointer to left child of the node
node *right; // the pointer to right child of the node
node *parent; // the pointer to parent node
};
And I am calling the createNewNode function from another function
temp = t->createNewNode(score,"");
The function runs properly for only one time and then it crashes while executing:
node* n = new node;
You need to allocate memory to the word field. You are trying to copy data into word with out allocating space for it.
change char *word to char word[100];
char *word; // this is a pointer to string, aka this is not a string
char word[100]; // this is a string
n->word is uninitialized. when you are using strcpy you are copying word content in an unknown address.
This result on unknown behavior (The first call look like it work and the second made the program crash). You need to allocate the memory space to hold word string inside the structure.
Your error is due to word not being allocated memory.
You could fix this using legacy C functionality like in the other answers, or you could actually write idomatic C++.
All of the initialization done in the createNewNode function should be done in the node constructor. You should use std::string instead of char* to avoid memory allocation failures like you currently have. You should also protect the members of your node class, instead providing mutators to attach/detach them from the tree so you don't need to do it manually.
Your program crashes in the following line,
strcpy(n->word,word);
because, n->word in struct node
char *word; // the word stored in the node
was not allocated any memory.
Use char array instead of char pointer or change the function definition like this:
node* createNewNode(int score, const char* word, int wordLen)
{ ^^^^
// Create a new node with the information available
node* n = new node;
n->left=NULL;
n->right = NULL;
n->parent = NULL;
n->score = score;
n->word = (char *) malloc(wordLen);
strcpy(n->word,word);
return n;
}
strcpy(n->word, word) copies the input string into n->word which has not been initialized. For that experession to work correcly n->word must point to an allocated buffer.
strdup function allocates that buffer for you and copies the input string into that buffer, e.g.:
n->word = strdup(word);

C++ binary search tree

Recently I have started playing around with C++, namely classes and pointers. I looked around for similar questions, but nothing helped.
I have a binary search tree class that holds some information in string format (well, char *), but after adding a new node to the tree, I cannot get the information back, as it returns junk.
Here is what my code looks like:
class Node
{
Node *lNode;
Node *rNode;
char *name;
public:
void setName(char *n) { name = n; }
char *getName() { return name; }
}
class Tree
{
Node *root;
Node *addNode(Node *, Node *);
public:
Tree() { root = NULL };
int addNewNode(Node *);
void print();
};
int Tree::addNewNode(Node *n)
{
root = addNode(root, n);
cout << root->getName() << endl; // this returns the name correctly
}
Node *Tree::addNode(Node *subtree, Node *node)
{
if(subtree== NULL)
{
subtree = node;
}
else if(node->getName() <= subtree->getLeft())
{
subtree->setLeft(addNode(subtree->getLeft(), node));
}
else
{
subtree->setRight(addNode(subtree->getRight(), node));
}
return subtree;
}
void Tree::print()
{
cout << root->getName() << endl; // this does not!
}
And this is where I call the methods:
Tree *myTree = new Tree();
Node *n = new Node();
n->setName(name);
myTree->addNewNode(n);
The tree variable is a private member attribute of an outer container class, and actually gets created outside that class to be passed into the constructor. When I invoke the addNewNode method, that adds a Node to the tree, but when I want to print out the name of the node stored in the root, it just comes up with junk. I guess there's a haywire pointer somewhere, but I cannot find it for the life of me.
Any help would be greatly appreciated.
I'll guess that you're passing in a string pointer name to setName and just copying the pointer to name (as opposed to reallocating and saving the string). Later, the original object is gone, and your object name is left pointing to garbage. Trying using std::string for name instead, or create your own memory with name = new char[ strlen(n) + 1 ] and strcpy/memcpy it in. And don't forget to delete [] name at object destruction if you go that route.
When root is null, you set it to city rather than node. There's your problem.

read access violation error

class Node{
private:
string name;
Node** adjacent;
int adjNum;
public:
Node();
Node(string, int adj_num);
Node(const Node &);
bool addAdjacent(const Node &);
Node** getAdjacents();
string getName();
~Node();
};
bool Node::addAdjacent(const Node &anode){
Node** temp;
temp= new Node*[adjNum+1];
for(int i=0;i<adjNum+1;i++)
temp[i]=adjacent[i];
temp[adjNum]=const_cast<Node *>(&anode);
delete[] adjacent;
adjacent=new Node*[adjNum+1];
adjacent=temp;
delete[] temp;
adjNum++;
return true;
}
int main()
{
Node node1("A",0);
Node node2("B",0);
node1.getName();
node1.addAdjacent(node2);
system("PAUSE");
return 0;
}
when the program comes to this part:
for(int i=0;i<adjNum+1;i++)
temp[i]=adjacent[i];
it says Access violation reading location 0xcccccccc. The class must allocate the memory fore adjacent, but I think it didn't how can I solve this problem?
adjacent=new Node*[adjNum+1];
adjacent=temp;
delete[] temp;
This looks like a bug. You probably meant to write:
adjacent = temp;
and that's it.
Also, I think the problem lies with
for(int i=0;i<adjNum+1;i++)
You're copying adjNum+1 elements, even though (I assume) adjacent only contains adjNum elements. Remove the +1 from the for loop.
Besides the issues strager mentioned, you might be missing initialization for adjacent, e.g. like this:
Node::Node(std::string name, unsigned adj_num)
: name(name)
, adjacent((adj_num > 0) ? new Node*[adj_num] : 0)
, adjNum(adj_num)
{}
Note the unsigned parameter, a negative adj_num is most likely meaningless in this context.
If you don't initialize adjacent, it contains some garbage value and dereferencing it or passing it to delete[] leads to undefined behaviour.