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.
Related
Provide a recursive function that takes a pointer to the middle of an infinite
doubly linked list along with an integer key and searches the list for the given key. The
list grows infinitely in both directions. Your algorithm should be able to find the key if it is
present in the list, otherwise it should continue the search infinitely.
This is The question i'm provided with and i can't understand how To recursivly search on both sides. either i'll have to write 2 functions i.e one for searching left other for right side.
but can it e searched in one function?
this is my code:
void searchmiddle(Node<T>* middle, int key,int index) {
if (middle == NULL) {
return ;
}
if (head == NULL) {
return ;
}
/* if (middle->next == head) {
return false ;
}*/
if (middle->data == key) {
cout << "key found at index "<<index << endl;
key = 0;
return ;
}
searchmiddle(middle->prev, key, index - 1);
searchmiddle(middle->next, key, index + 1);
}
code works for key next to middle pointer..
You could relay the call to a function that instead takes two Node<T>*, left and right. You then check if either one is the correct node and return if anyone is, otherwise you call the same function again recursively while stepping both left and `right.
template<class T>
Node<T>* searchmiddle(Node<T>* left, Node<T>* right, const T& key) {
if (left->data == key) return left;
if (right->data == key) return right;
return searchmiddle(left->prev, right->next, key);
}
template<class T>
Node<T>* searchmiddle(Node<T>* middle, const T& key) {
return searchmiddle(middle, middle->next, key);
}
This is purely theoretical though since it'll most probably stop working when the stack is full. It also doesn't check for nullptr since the list is said to be infinite.
Nothing in the requirement says anything about printing an index so I made it return a pointer to the found Node<T> instead.
You should not use recursion, because the requirement is that the search should continue infinitely for as long as there is no match. The call stack is limited, and recursion consumes it, meaning the recursion cannot go on indefinitely.
By consequence, the search should happen through iteration and not recursion.
You should use two pointers, one that will move along the prev pointers to the left, and the other that will move along the next pointers to the right. As apparently it is needed to report the index where the match was found, you should accompany those two pointers with an index.
There should not be a reference to a head pointer (where is it defined?), as an infinite list has no head. The challenge description suggests that the list extends continually in both directions, so there will be no end node like a head or a tail.
The code could be something like this:
void searchmiddle(Node<T>* middle, int key, int index) {
Node<T>* left = middle;
int leftIndex = index;
Node<T>* right = middle->next;
int rightIndex = index + 1;
while (1) { // Search continues as long there is no match
if (left->data == key) {
cout << "key found at index " << leftIndex << endl;
return;
}
left = left->prev;
leftIndex--;
if (right->data == key) {
cout << "key found at index " << rightIndex << endl;
return;
}
right = right->prev;
rightIndex++;
}
}
This is quite a theoretical challenge, as the only way to have a really infinite linked list, is to make it circular. It also means that there is a possibility that the key will never be found giving you a function that never finishes.
This is the function that I don't understand:
void showTree (node * tree, int cont) {
if (tree == NULL) {
return;
}
else {
showTree (tree-> right, cont + 1);
for (int i = 0; i <cont; i ++) {
cout << " ";
}
cout << tree-> data << endl;
showTree (tree-> left, cont + 1);
}
}
I do not understand:
How do you get to the for loop if that function is always called recursively?
How are tree items displayed if that function is always called recursively?
If someone could explain to me how this feature works I would really appreciate it.
How do you get to the for loop if that function is always called recursively?
The function returns immediately if tree == NULL, so it may continue onto the for loop.
How are tree items displayed if that function is always called recursively?
The output is produced by the for loop and the next statement, so same reasoning.
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
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.
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.