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.
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.
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.
For some reason my script for processing the bone hierarchy only finds max two children for a bone, and ignores the rest. I can't seem to pinpoint what I'm doing wrong in my script. The GetNode function seems to run only two times even if mNumChildrenis more than two.
void GetNode(aiNode *node) {
string name = (string)node->mName.data;
//Third child does not get putput
cout << name << endl;
for (int i = 0; i < node->mNumChildren; i++) {
node = node->mChildren[i];
GetNode(node);
}
}
Changing node = node->mChildren[i]; GetNode(node) to GetNode(node>mChildren[i]) seemed to fix it. However I am not sure why.
It looks like you are traversing in a depth-first manner. You could try iterating children first in a breadth-first manner by,
for (auto node : node->mChildren) {
std::cout << node->mName.data << "\n";
}
for (auto node : node->mChildren) {
GetNode(node);
}
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.
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.