Getting signal sigsegv while sorting a linked list - singly-linked-list

I am trying to sort a linked list,but i getting this segmentation fault while sorting, tried debuggig but cant find the problem though.
here is the sorting function:
void Asort(struct lol **head_ref)
{
cout<<"Entered in asort function\n";
/// Sorting Asendingly
int temp1; /// to store the temp value
struct lol* temp = *head_ref;
struct lol* next;
while(temp!=NULL)
{
cout<<"Entered in while loop until null\n";
next=temp->next;
cout<<"log: " << next->element;
if(temp->element > next->element && next!=NULL)
{
cout<<"Entered in If condition inside while loop\n";
temp1=next->element;
next->element=temp->element;
temp->element=temp1;
}
temp=temp->next;
}
cout<<"Sorted Asending Successfully\n";
}
Here is calling statement :
Asort(*head)

if(temp->element > next->element && next!=NULL)
There is no point in checking whether next is NULL after you have dereferenced it: if it was NULL, you are already dead.
The order matters; next != NULL && temp->element > next->element would work better.
You have similar bug elsewhere in the program, e.g.
next=temp->next;
cout<<"log: " << next->element; // will crash here if next==NULL

Related

Preorder Traversal (Binary Tree) - Iterative Method

I am implementing Preorder Traversal of Binary Tree (without recursion). The following code runs into an infinite loop. I cannot understand what's happening
void Tree::n_preorder()
{
Node* temp;
stack s;
cout<<"\nPreorder: ";
while(1)
{
s.push(root);
while(1)
{
temp = s.pop();
cout<<temp->data;
if(temp->right)
{
s.push(temp->right); //Push right child
}
if(s.isEmpty())
{
break;
}
if(temp->left)
{
s.push(temp->left); //Push left child
}
}
}
}
isEmpty() function of Stack
int isEmpty()
{
return top==-1;
}
The outer loop is never exited: its while condition is always true, and it has no break. The only break you have will break out of the inner loop, but not the outer one.
You should not need nested loops to do this. And when you have just one loop, it makes no sense to break out of it without putting the left child on the stack, so remove that conditional break, and instead make !s.isEmpty() the condition of your loop:
void Tree::n_preorder()
{
Node* node;
stack nodeStack;
cout << "\nPreorder:";
nodeStack.push(root);
while (!nodeStack.isEmpty())
{
node = nodeStack.pop();
cout << " " << node->data;
// As a stack is LIFO (last-in-first-out), we add the node's children
// on the stack in reversed order, so they get output in the correct order.
if (node->right)
{
nodeStack.push(node->right);
}
if (node->left)
{
nodeStack.push(node->left);
}
}
}
Some other remarks:
I do not find it useful to have comments like "push left child"... as that is just repeating -- almost verbatim -- what one can already see in the corresponding line of code. Comments should be made about a higher level of abstraction, and give some explanation as to "why?". I added such a comment in the above code to illustrate this point.
Use more descriptive variable names. temp and s are not giving away much.
You'll want to output a space to separate the different data outputs.

Inserting a basic singly linked list node seems to break my c++ code?

Singly Linked List and Node classes and the start of the main function, where I wrote a brief outline of the code functionality. The issue is toward the end of the main function. I wrote '...' in place of what I believe to be irrelevant code because it simply parses strings and assigns them to the string temp_hold[3] array.
#include <bits/stdc++.h>
using namespace std;
class Node {
public:
string value;
string attr;
string tagname;
Node *next;
Node(string c_tagname, string c_attr, string c_value) {
this->attr = c_attr;
this->value = c_value;
this->tagname = c_tagname;
this->next = nullptr;
}
};
class SinglyLinkedList {
public:
Node *head;
Node *tail;
SinglyLinkedList() {
this->head = nullptr;
this->tail = nullptr;
}
void insert_node(string c_tagname, string c_attr,string c_value) {
Node *node = new Node(c_tagname,c_attr, c_value);
if (!this->head) {
this->head = node;
} else {
this->tail->next = node;
}
this->tail = node;
}
};
int main(int argc, char **argv) {
/* storage is a vector holding pointers to the linked lists
linked lists are created and the linked list iterator sll_itr is incremented when
previous line begins with '</' and the currentline begins with '<'
linked lists have nodes, which have strings corresponding to tagname, value, and attribute
*/
SinglyLinkedList *llist = new SinglyLinkedList();
vector<SinglyLinkedList*> sllVect;
sllVect.push_back(llist);
auto sll_itr = sllVect.begin();
string temp_hold[3];
// to determine new sll creation
bool prev = false;
bool now = false;
//input
int num1, num2;
cin >> num1; cin >> num2;
//read input in
for (int i = 0; i <= num1; ++i) {
string line1, test1;
getline(cin, line1);
test1 = line1.substr(line1.find("<") + 1);
//determine to create a new linked list or wait
if (test1[0] == '/') {
prev = now;
now = true;
} else {
//make a node for the data and add to current linked list
if (i > 0) {
prev = now;
now = false;
//if last statement starts with '</' and current statment starts with '<'
// then start a new sll and increment pointer to vector<SinglyLinkedList*>
if (prev && !now) {
SinglyLinkedList *llisttemp = new SinglyLinkedList();
sllVect.push_back(llisttemp);
sll_itr++;
}
}
//parse strings from line
int j = 0;
vector<string> datastr;
vector<char> data;
char test = test1[j];
while (test) {
if (isspace(test) || test == '>') {
string temp_for_vect(data.begin(),data.end());
if (!temp_for_vect.empty()) {
datastr.push_back(temp_for_vect);
}
data.clear();
} else
if (!isalnum(test)) {
} else {
data.push_back(test);
}
j++;
test = test1[j];
}
//each node has 3 strings to fill
int count = 0;
for (auto itrs = datastr.begin(); itrs!=datastr.end(); ++itrs) {
switch (count) {
case 0:
temp_hold[count]=(*itrs);
break;
case 1:
temp_hold[count]=(*itrs);
break;
case 2:
temp_hold[count]=(*itrs);
break;
default:
break;
}
count++;
}
}
cout << "before storing node" << endl;
(*sll_itr)->insert_node(temp_hold[0], temp_hold[1], temp_hold[2]);
cout << "after" << endl;
}
cout << "AFTER ELSE" << endl;
return 0;
}
And here is the line that breaks the code. The auto sll_itr is dereferenced which means *sll_itr is now a SinglyLinkedList* and we can call the insert_node(string, string, string) to add a node to the current linked list. However when I keep the line, anything after the else statement brace does not run, which means the cout<<"AFTER ELSE"<< endl; does not fire. If I remove the insert_node line, then the program runs the cout<<"AFTER ELSE"<< endl; I am unsure what the issue is.
(*sll_itr)->insert_node(temp_hold[0],temp_hold[1],temp_hold[2]);
cout << "after" << endl;
} //NOT HANGING. This closes an else statement.
cout << "AFTER ELSE" << endl;
return 0;
}
Compiled as g++ -o myll mylinkedlist.cpp and then myll.exe < input.txt And input.txt contains
8 3
<tag1 value = "HelloWorld">
<tag2 name = "Name2">
</tag2>
</tag1>
<tag5 name = "Name5">
</tag5>
<tag6 name = "Name6">
</tag6>
Your linked list isn't the problem, at least not the problem here.
A recipe for disaster in the making: retaining, referencing, and potentially manipulating, an iterator on a dynamic collection that potentially invalidates iterators on container-modification. Your code does just that. tossing out all the cruft between:
vector<SinglyLinkedList*> sllVect;
sllVect.push_back(llist);
auto sll_itr = sllVect.begin();
....
SinglyLinkedList *llisttemp = new SinglyLinkedList();
sllVect.push_back(llisttemp); // HERE: INVALIDATES sll_iter on internal resize
sll_itr++; // HERE: NO LONGER GUARANTEED VALID; operator++ CAN INVOKE UB
To address this, you have two choices:
Use a container that doesn't invalidate iterators on push_back. There are really only two sequence containers that fit that description: std::forward_list and std::list.
Alter your algorithm to reference by index`, not by iterator. I.e. man your loop to iterate until the indexed element reaches end-of-container, then break.
An excellent discussion about containers that do/do-not invalidate pointers and iterators can be found here. It's worth a read.

Insertion and deletion in a stack using linked list

The program is about insertion and deletion in a stack using ling lists.The push works fine but there is problem in the deletion the pop() function has some
error. Every time i try to delete something it gives infinite error with underflow. ie. the top pointer is always null.
#include<iostream>
#include<stdlib.h>
#include<process.h>
using namespace std;
struct node
{
int info;
node *next;
}*top,*save,*newptr,*ptr;
node *create_new_node(int);
void push(node*);
void pop();
void display(node*);
int main()
{
top=NULL;
int inf;
char ch='y';
while(ch=='y'||ch=='Y')
{
newptr=new node;
cout<<"\nEnter the info to be added in the beginning of the stack\n";
cin>>inf;
if(newptr==NULL)
cout<<"\nCannot create new node.ABORTING!!\n";
else
{
newptr=create_new_node(inf);
cout<<"\nPress enter to continue\n";
system("pause");
}
push(newptr);
cout<<"\nthe info has been inserted in the stack\n";
cout<<"\nThe stack now is\n";
display(newptr);
cout<<"\ndo you wish to add more elements to the stack.\nIf yes then
press y or else press n\n";
cin>>ch;
if(ch=='n'||ch=='N')
{
cout<<"\ndo you to delete elements from the stack\n";
cout<,"\nIf yes then press d else press n\n";
cin>>ch;
if(ch=='d'||ch=='D')
{
while(ch=='d'||ch=='D')
{
pop();
cout<<"\npress d to delete more elements y to add more
elements and n to exit\n";
cin>>ch;
}
}
}
}
delete(ptr);
delete(newptr);
delete(top);
delete(save);
return 0;
}
node* create_new_node(int n)
{
ptr=new node;
ptr->info=n;
ptr->next=NULL;
return ptr;
}
void push(node *np)
{
if(top==NULL)
top=np;
else
{
save=top;
top=np;
np->next=save;
}
}
void pop()
{
if(top==NULL)
cout<<"underflow";
else
{
ptr=top;
top=top->next;
delete ptr;
}
}
void display(node *np)
{
while(np!=NULL)
{
cout<<np->info<<"->";
np=np->next;
}
}
There are multiple bugs in the shown code.
Your main bug:
while(ch=='d'||ch=='D')
{
pop();
cout<<"\npress d to delete more elements y to add more elements and n to exit\n";
}
At this point, when ch is 'd' or 'D' execution will enter the while loop, of course. A call to pop() is made, which removes the topmost element from the stack, prints a message, and repeats the while loop.
At this point your program will make an important discovery that ch is still either 'd' or 'D'. Nothing has changed its value. A computer program always does exactly what you tell it to do, unfortunately, instead of what you think you want it to do. No matter how hard you look here, you will never find any code here that ever changes the value of ch. It will remain at its current value forever. And so the while loop runs again. And again. And again. Nothing ever changes the value of ch, at this point, so you have an infinite loop.
Additionally, in your main:
newptr=new node;
This pointer's value is later compared to NULL; and if not ... it gets completely overwritten by
newptr=create_new_node(inf);
This accomplishes absolutely nothing, except leaking memory. This code appears to be leftover junk, and should be cleaned up after fixing the faulty while loop logic.

Insertion error in Binary Search tree

void BST::insert(string word)
{
insert(buildWord(word),root);
}
//Above is the gateway insertion function that calls the function below
//in order to build the Node, then passes the Node into the insert function
//below that
Node* BST::buildWord(string word)
{
Node* newWord = new Node;
newWord->left = NULL;
newWord->right = NULL;
newWord->word = normalizeString(word);
return newWord;
}
//The normalizeString() returns a lowercase string, no problems there
void BST::insert(Node* newWord,Node* wordPntr)
{
if(wordPntr == NULL)
{
cout << "wordPntr is NULL" << endl;
wordPntr = newWord;
cout << wordPntr->word << endl;
}
else if(newWord->word.compare(wordPntr->word) < 0)
{
cout << "word alphabetized before" << endl;
insert(newWord,wordPntr->left);
}
else if(newWord->word.compare(wordPntr->word) > 0)
{
cout << "word alphabetized after" << endl;
insert(newWord, wordPntr->right);
}
else
{
delete newWord;
}
}
So my problem is this: I call the gateway insert() externally (also no problems with the inflow of data) and every time it tells me that the root, or the initial Node* is NULL. But that should only be the case before the first insert. Each time the function is called, it sticks the newWord right at the root.
To clarify: These functions are part of the BST class, and root is a Node* and a private member of BST.h
It's possible it is quite obvious, and I have just been staring too long. Any help would be appreciated.
Also, this is a school-assigned project.
Best
Like user946850 says, the variable wordPntr is a local variable, if you change it to point to something else it will not be reflected in the calling function.
There are two ways of fixing this:
The old C way, by using a pointer to a pointer:
void BST::insert(Node *newWord, Node **wordPntr)
{
// ...
*wordPntr = newWord;
// ...
}
You call it this way:
some_object.insert(newWord, &rootPntr);
Using C++ references:
void BST::insert(Node *newWord, Node *&wordPntr)
{
// Nothing here or in the caller changes
// ...
}
To help you understand this better, I suggest you read more about scope and lifetime of variables.
The assignment wordPntr = newWord; is local to the insert function, it should somehow set the root of the tree in this case.

Strcmp Error in Binary Search Tree Insertion (Recursion)?

i'm trying to implement some functions that allow me to add "Books" to a binary search tree for the "Student" class, but I'm getting a strange error:
msvcr100d.dll!strcmp(unsigned char * str1, unsigned char * str2) Line 83 Asm
The program is entirely in C/C++, so I'm not sure why its returning an assembly language error? My first thought is something is wrong with my use of strcmp, and the Call Stack shows Line 188 as the last executed statement (before the above error), which means I'm probably messing up my recursion somewhere. I am calling the insertBook() function of "Student", so here is my "Student" class. Any help? Thanks.
class Student : public Personnel { //inherit from Personnel
public:
Book *bookTree;
Book* searchBookTree(Book *bookNode, char *title) {
if ((strcmp(title, bookNode->title)) < 0) //***LINE 188
return searchBookTree(bookNode->left, title);
else if ((strcmp(title, bookNode->title)) > 0)
return searchBookTree(bookNode->right, title);
else
return bookNode;
}
void insertBook(Book *node) {
Book *newBook, *parent;
newBook = node;
newBook->left = NULL;
newBook->right = NULL;
if (bookTree == NULL) { //if bookTree is empty
bookTree = newBook;
}
else {
parent = searchBookTree(bookTree, newBook->title);
newBook->left = parent->left;
newBook->right = parent->right;
}
}
void printBooks(Book *top) {
Book *root = top;
if (root != NULL) {
printBooks(root->left);
cout << "BOOK LIST" << endl;
cout << "Title:\t\t" << root->title << endl;
cout << "URL:\t\t" << root->url << endl;
printBooks(root->right);
}
}
void display() {
Personnel::display();
cout << "STUDENT" << endl;
cout << "Level:\t\t" << getLevel() << endl;
printBooks(bookTree); cout << endl;
}
Student(char *cName, char *cBirthday, char *cAddress, char *cPhone, char *cEmail, level gradeLevel)
: Personnel(cName, cBirthday, cAddress, cPhone, cEmail)
{
bookTree = NULL;
setLevel(gradeLevel);
}
};
Book* searchBookTree(Book *bookNode, char *title) {
if ((strcmp(title, bookNode->title)) < 0) //***LINE 188
// What happens if bookNode->left == NULL ???
return searchBookTree(bookNode->left, title);
else if ((strcmp(title, bookNode->title)) > 0)
// What happens if bookNode->right== NULL ???
return searchBookTree(bookNode->right, title);
else
return bookNode;
}
you'll need a termination point in your search function. At the top, I'd first check if bookNode == NULL.
Your recursive search an important termination test missing! At some point, you hit the bottom of the tree without finding the item. And so your search function is called with a null pointer for the tree node! The problem is not in strcmp, but in the null pointer in one of the argument expressions.
You have only considered the case when the item exists in the tree and is eventually found, neglecting the not-found case.
Programmers are not to be measured by their ingenuity and their logic but by the completeness of their case analysis.
Alan J. Perlis, Epigram #32
Your insert routine has problems. I suggest you make your searchBookTree just return a null pointer when it doesn't find anything. Do not use that routine in the implementation of insertBook. Rather, you can write insertBook recursively also:
private:
// Inserts bookNode into tree, returning new tree:
Book *insertBookHelper(Book *tree, Book *bookNode) {
if (tree == NULL)
return bookNode; // bookNode becomes new tree
// no need to call strcmp twice!!!
int cmp = strcmp(title, bookNode->title);
if (cmp < 0) {
tree->left = insertBookHelper(tree->left, bookNode->title);
else if (cmp > 0)
tree->right = insertBookHelper(tree->right, bookNode->title);
else {
// Uh oh! Tree already contains that title, what to do?
// Answer: update!
// I don't know how to write this because I don't know
// how your Book class handles the memory for the strings,
// and what other members it has besides the title.
// this could be a possibility:
// bookNode->left = tree->left; // install same child pointers
// bookNode->right = tree->right; // into bookNode.
// *tree = *bookNode; // if Book has a sane copy constructor!!!
}
return tree;
}
public:
void insertBook(Book *node) {
tree = insertBookHelper(tree, node);
}
Do you see how the recursion works? It's a little different from the pure search. Each recursive level handles the insertion into the subtree and returns the new subtree. Often, the returned tree is exactly the same as the tree that went in! But when inserting into an empty tree, the returned tree is not the same: the tree that went in is a null pointer, but a non-null pointer comes out. This trick of pretending that we are making a new tree and returning it as a replacement for the old tree makes for smooth code.