I have been experimenting with binary trees. I am trying to build an expression tree with the below c++ code. but, i keep getting segmentation fault(core dumped) during runtime
#include<iostream>
#include<ctype.h>
#include<vector>
using namespace std;
struct tree{
char data;
tree *left=NULL;
tree *right=NULL;
tree *parent=NULL;
};
tree* newNode(char d)
{
struct tree* node = new tree;
//struct tree* nodep = &node;
node->data = d;
return node;
}
tree* parseTree(string expression)
{
vector<char> tokens;
for(int i = 0; i<expression.size(); i++)
tokens.push_back(expression[i]);
struct tree* currentNode = newNode(' ');
struct tree* prevNode = new tree;
for(int i = 0; i<tokens.size(); i++)
{
if(tokens[i]=='(')
{
currentNode->left = newNode(' ');
prevNode = currentNode;
currentNode = currentNode->left;
currentNode->parent = prevNode;
}
else if(tokens[i]=='+'||tokens[i]=='-'||tokens[i]=='*'||tokens[i]=='/')
{
currentNode->data = tokens[i];
prevNode = currentNode;
currentNode = currentNode->right;
currentNode->parent = prevNode;
}
else if(isdigit(tokens[i]))
{
currentNode->data = tokens[i];
prevNode = currentNode;
currentNode = currentNode->parent;
}
else if(tokens[i]==')')
{
prevNode = currentNode;
currentNode = currentNode->parent;
}
}
return currentNode;
}
int main()
{
string expression = "(3+(4*5))";
struct tree* root = parseTree(expression);
return 0;
}
I tried different things but i couldn't get rid of this error
what am i missing?
why do i get this error?
how to rectify this?
else if(tokens[i]=='+'||tokens[i]=='-'||tokens[i]=='*'||tokens[i]=='/')
{
currentNode->data = tokens[i];
prevNode = currentNode;
currentNode = currentNode->right;
currentNode->parent = prevNode;
}
No code ever sets any right to anything other than NULL. So in the last line, currentNode is NULL and you are dereferencing a NULL pointer.
Also, take a look here:
struct tree* prevNode = new tree;
This value is never used and when the value is changed, the tree you allocated here is leaked.
This part uses ->right, which was never set:
else if(tokens[i]=='+'||tokens[i]=='-'||tokens[i]=='*'||tokens[i]=='/')
{
currentNode->data = tokens[i];
prevNode = currentNode;
currentNode = currentNode->right;
currentNode->parent = prevNode; // SEGFAULT
}
So you are trying to write to address 0 + some offset, which you are not allowed to.
Related
I am confused a bit. I narrowed down it to:
Why having this line:
Node *root, *rootSafe = NULL;
give error:
Segmentation fault(core dumped)
While just switching it like below:
Node *rootSafe, *root = NULL;
runs perfect.
Here is the code, you can test.
#include <iostream>
using namespace std;
struct Node{
int data;
Node *left, *right;
Node(int d){
this->data = d;
this->left = this->right = NULL;
}
};
Node *newNode(int d){
Node *temp = (Node *)malloc(sizeof(Node));
temp->data = d;
temp->left = temp->right = NULL;
return temp;
}
void printInorder(Node *root){
if(root == NULL){
return;
}
else{
printInorder(root->left);
cout << "--" << root->data;
printInorder(root->right);
}
}
int main()
{
//cout << "Hello World";
Node *rootSafe, *root = NULL;
int arr[] = {5, 3, 1, 4, 6};
int sizeArr = sizeof(arr)/sizeof(arr[0]);
for(auto i = 0; i < sizeArr; i++){
if(root == NULL){
rootSafe = newNode(arr[i]);
root = rootSafe;
}
else{
while(root != NULL){
if(arr[i] < root->data){//Move left
if(root->left == NULL){
root->left = newNode(arr[i]);
root = NULL;
}
else{
root = root->left;
}
}
else{//Move right
if(root->right == NULL){
root->right = newNode(arr[i]);
root = NULL;
}
else{
root = root->right;
}
}
}
}
root = rootSafe;
}
cout << "\n Print Inorder: ----"; printInorder(rootSafe);
return 0;
}
Without fiddling with your code, I think this:
Node *root, *rootSafe = NULL;
Doesn't do what you think it does. Do you think it sets both to NULL? It doesn't. root gets some random value and rootSafe gets NULL.
This might be what you really want:
Node *root = NULL, *rootSafe = NULL;
Frankly, I personally hate (and it's against coding conventions at some work places) specifying multiple variables on the same line. You will not find this in my code. Instead, you will see:
Node * root = nullptr;
Node * rootSafe = nullptr;
Note also that in modern C++, NULL is not a pointer. Get in the habit of using nullptr.
You are using root here:
if(root == NULL){
Your original declaration
Node *root, *rootSafe = NULL;
doesn't initialize root, leaving it with indeterminate value. Therefore, root with some random invalid value may be dereferenced and it may lead to Segmentation Fault.
To avoid this, you should initialize root before using that.
It can be done in declaration:
Node *root = NULL, *rootSafe = NULL;
Or before the loop:
root = NULL;
for(auto i = 0; i < sizeArr; i++){
Node *root, *rootSafe = NULL;
Node *rootSafe, *root = NULL;
The first line leaves root uninitialized. This causes undefined behaviour while access root.
The second line leaves rootSafe uninitialized but the var later initialized rootSafe = newNode(arr[i]);.
I have a linked list in C++, after inserting several nodes now I see that all of them are the same, although I'm using different values to add to node each time, but it's like all of them are the same, even when trying to change a node all of them are changing together or it's the same node that is always being returned, I don't know.
class node
{
public:
int ochance = 3;
string question;
string option1;
int peopleeffectop1;
int courteffectop1;
int treasuryeffectop1;
string option2;
int peopleeffectop2;
int courteffectop2;
int treasuryeffectop2;
node *next;
};
class list
{
private:
node *head, *tail;
public:
list()
{
head=NULL;
tail=NULL;
}
void createnode(int value , string q , string ans1 , int ans1ef1 , int ans1ef2, int ans1ef3 , string ans2, int ans2ef1 , int ans2ef2, int ans2ef3 )
{
node *temp = new node;
temp->ochance = value;
temp->question = q;
temp->option1 = ans1;
temp->peopleeffectop1 = ans1ef1;
temp->courteffectop1 = ans1ef2;
temp->treasuryeffectop1 = ans1ef3;
temp->option2 = ans2;
temp->peopleeffectop2 = ans2ef1;
temp->courteffectop2 = ans2ef2;
temp->treasuryeffectop2 = ans2ef3;
temp->next = NULL;
if(head == NULL)
{
head = temp;
tail = temp;
temp = NULL;
}
else
{
tail->next = temp;
tail = temp;
}
}
node getnth(int pos)
{
node* tmp = new node;
tmp = head;
int i = 0;
while(tmp!=NULL)
{
if (i=pos)
{
return *tmp;
}
i++;
tmp = tmp->next;
}
}
int getlen()
{
node* tmp = new node;
tmp = head;
int i = 0;
while(tmp!=NULL)
{
i++;
tmp = tmp->next;
}
return i;
}
void minus(int pos)
{
node* tmp = new node;
tmp = head;
int i = 0;
while(tmp!=NULL)
{
if (i=pos)
{
tmp->ochance -=1;
}
i++;
tmp = tmp->next;
}
}
void delete_first()
{
node *temp = new node;
temp = head;
head = head->next;
delete temp;
}
void delete_last()
{
node *current = new node;
node *previous = new node;
current = head;
while(current->next != NULL)
{
previous = current;
current = current->next;
}
tail = previous;
previous->next = NULL;
delete current;
}
void delete_position(int pos)
{
node *current = new node;
node *previous = new node;
current = head;
for(int i = 1; i < pos; i++)
{
previous = current;
current = current->next;
}
previous->next = current->next;
}
};
For starters many member functions has a memory leak as for example in this function
node getnth(int pos)
{
node* tmp = new node;
tmp= head;
//
At first memory was allocated and its address was stored in the pointer tmp and then the pointer is reassigned. As a result the address of the allocated memory is lost and the memory is not deleted.
These statements
node* tmp = new node;
tmp= head;
must be substituted for this one statement
node* tmp = head;
Moreover this function
node getnth(int pos)
{
node* tmp = new node;
tmp= head;
int i =0 ;
while(tmp!=NULL){
if (i=pos) {
return *tmp;
}
i++;
tmp = tmp->next;
}
}
has undefined behavior in case when pos is higher than there are nodes in the list. In this case the function returns nothing.
In the function minus there is used the assignment operator instead of the comparison operator
while(tmp!=NULL){
if (i=pos) {
^^^^^
In this function
void delete_first()
{
node *temp=new node;
temp=head;
head=head->next;
delete temp;
}
there is no check whether head is equal to NULL and tail is not adjusted if it is point to the first node.
The same problems are also in the function delete_last only that instead of the adjacent of the tail node as in the previous function you have to adjust the head node.
This function delete_position has the same drawbacks as the previous functions but also it has a bug in the loop
for(int i=1;i<pos;i++)
A node at position 1 will never be deleted.
I am trying to delete a node from the end of the doubly linked list,but i am getting:
segmentation fault
i have added different functions to add the node, from beginning , from end , and at any position.I checked the insertion of nodes,its working fine,the DLL is displayed correctly,but when it comes to deleting function,it gives segmentation fault.
struct Node {
Node* left;
Node* right;
int data;
};
Node* head = NULL;
void insertion_At_End(int element) {
Node* ptr = head;
Node* temp = new Node;
temp->left = temp->right = NULL;
temp->data = element;
if(head==NULL) {
head = temp;
} else {
while(ptr->right!=NULL) {
ptr = ptr->right;
}
temp->left = ptr->right;
ptr->right = temp;
}
}
void insertion_At_Beg(int element) {
Node* ptr = head;
Node* temp = new Node;
temp->left = temp->right = NULL;
temp->data = element;
if(head==NULL) {
head = temp;
} else {
temp->right = ptr;
ptr->left = temp;
head = temp;
}
}
void insertion_At_Pos(int element , int position , int length) {
Node* ptr;
Node* temp = new Node;
temp->left = temp->right = NULL;
temp->data = element;
int counter = 1;
if(position==1) {
insertion_At_Beg(element);
}
else if(position==length) {
insertion_At_End(element);
}
else {
ptr = head;
while(counter!=(position-1)) {
ptr = ptr->right;
counter++;
}
temp->right = ptr->right;
ptr->right->left = temp;
temp->left = ptr;
ptr->right = temp;
}
}
void deletion_At_End() {
Node *ptr = head;
while(ptr->right!=NULL) {
ptr = ptr->right;
}
ptr->left->right=NULL;
delete ptr;
}
I get the error if i have only one element in the list. When you have only one element in the list you can not set what it is in its left's right pointing to NULL because it does not exist! This works for me:
void deletion_At_End() {
Node *ptr = head;
while(ptr->right!=NULL) {
ptr = ptr->right;
}
if(ptr->left == NULL){
delete ptr;
}
else{
ptr->left->right=NULL;
delete ptr;
}
}
I have a function and it is suppose to organize a dictionary of stemmed words. I have a function call inserted then suppose to place it in the right alphabetical order. Adding to the front and middle of the list works, but adding to the back doesn't. I've looked at several sources and I can't tell what's wrong.
void dictionary::insert(string s) {
stem* t = new stem;
t->stem = s;
t->count =0;
t->next = NULL;
if (isEmpty()) head = t;
else {
stem* temp = head;
stem* prev = NULL;
while (temp != NULL) {
if (prev == NULL && t->stem < temp ->stem) {
head = t;
head->next = temp;
}
prev = temp;
temp = temp->next;
if(t->stem > prev->stem && t->stem < temp->stem ){
prev->next =t;
t->next=temp;
}
}
if(temp == NULL && t->stem > prev->stem){
prev->next=t;
}
}
}
The statement if(temp->next=NULL) does not result in a boolean but rather an assignment. This is why the insert to the end of the list doesn't appear to work.
if (temp->next=NULL) {
prev->next = t;
}
Note the usage of a single equal. The effect of this is to set the temp->next to NULL and then evaluate if (NULL) witch will be always false. You should use ==.
This will probably do the job: (sorry, I don't have a compiler right now to test it)
#include <string>
struct node;
struct node
{
node* next;
std::string value;
};
node* head = NULL;
void insert(const std::string& word)
{
node* n = new node;
n->value = word;
node* temp = head;
node** tempp = &head;
while (true)
{
if (temp == NULL or temp->value > word)
{
n->next = temp;
*tempp = n;
return;
}
temp = temp->next;
tempp = &temp->next;
}
}
I have a segmentation fault in my destructor but I'm not quite sure why. The code is for a map of key/value pairs which are stored in a Node array and chained to avoid collisions.
template<class V>
map<string, V>::~map()
{
for(unsigned int i = 0; i < SIZE; i++){
if(hashArray[i] != NULL){
Node* tmpNode = hashArray[i];
Node* currentNode = hashArray[i];
while(currentNode->next != NULL){
currentNode = currentNode->next;
delete tmpNode;
tmpNode = currentNode;
}
delete tmpNode;
}
}
delete [] hashArray;
}
The debugger points to this line but I'm sure I'm not going out of range.
while(currentNode->next != NULL){
Any other code can be provided if need be. thank you in advance for your help. :)
I cleaned it up a bit by getting rid of the duplicate hashArray[i]s. Also got rid of the duplicate checks for null:
template<class V>
map<string, V>::~map()
{
for(unsigned int i = 0; i < SIZE; i++) {
Node* currentNode = hashArray[i];
while(currentNode) {
Node* next = currentNode->next;
delete currentNode;
currentNode = next;
}
}
delete [] hashArray;
}