Implementing a recursive Void function (Finding height of Binary Search Tree) - c++

I need to implement a void function that computes the height of each node in a binary tree and stores it in each node. I've found a few solutions online that are recursive in nature but they return int. Examples include (https://www.geeksforgeeks.org/write-a-c-program-to-find-the-maximum-depth-or-height-of-a-tree/). The difference between the model answer, besides that it is not a void function, is that it also does not store the height in each node.
This is my attempt at the solution, but I can't seem to get the code to work, nor refit the model answer to recursively apply in a void function. When I run my code in the helper code to test, it doesn't even show any output.
void computeHeight(Node *n) {
Node* ltraverser = n;
Node* rtraverser = n;
int lheight = 0;
int rheight =0;
if (n == NULL) {
n->height = 0;
}
while (ltraverser->left != NULL) {
ltraverser = ltraverser->left;
lheight += 1;
}
while (rtraverser->right != NULL) {
rtraverser = rtraverser->right;
lheight += 1;
}
if (lheight > rheight) {
n->height = lheight;
}
else {
n->height = rheight;
}
computeHeight(n->left);
computeHeight(n->right);
}
For reference:
The starter code below defines a class called "Node" that has two child pointers ("left" , "right") and an integer "height" member variable. There is also a constructor Node() that initializes the children to nullptr and the height to -1.
/*
The height of a node is the number of edges in
its longest chain of descendants.
Implement computeHeight to compute the height
of the subtree rooted at the node n. Note that
this function does not return a value. You should
store the calculated height in that node's own
height member variable. Your function should also
do the same for EVERY node in the subtree rooted
at the current node. (This naturally lends itself
to a recursive solution!)
Assume that the following includes have already been
provided. You should not need any other includes
than these.
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string>
You have also the following class Node already defined.
You cannot change this class definition, so it is
shown here in a comment for your reference only:
class Node {
public:
int height; // to be set by computeHeight()
Node *left, *right;
Node() { height = -1; left = right = nullptr; }
~Node() {
delete left;
left = nullptr;
delete right;
right = nullptr;
}
};
*/
For testing the code
// This function prints the tree in a nested linear format.
void printTree(const Node *n) {
if (!n) return;
std::cout << n->height << "(";
printTree(n->left);
std::cout << ")(";
printTree(n->right);
std::cout << ")";
}
Node *n = new Node();
n->left = new Node();
n->right = new Node();
n->right->left = new Node();
n->right->right = new Node();
n->right->right->right = new Node();
computeHeight(n);
printTree(n);
std::cout << std::endl << std::endl;
printTreeVertical(n);
delete n;
n = nullptr;
return 0;
}

Instead of returning node height just recurisvely call computeHeight on left and right nodes, then store maximum height in node structure.
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string>
#include <algorithm>
class Node {
public:
int height;
Node *left, *right;
Node() { height = -1; left = right = nullptr; }
~Node() {
delete left;
left = nullptr;
delete right;
right = nullptr;
}
};
void computeHeight(Node *node) {
if (node == nullptr) {
return;
}
computeHeight(node->left);
computeHeight(node->right);
int leftHeight = -1;
int rightHeight = -1;
if (node->left != nullptr) {
leftHeight = node->left->height;
}
if (node->right != nullptr) {
rightHeight = node->right->height;
}
node->height = std::max(leftHeight, rightHeight) + 1;
}
void printNode(Node *n, int level = 0) {
if (n == nullptr) {
return;
}
std::cout << std::string(level * 2, ' ') << "Height = " << n->height << "\n";
printNode(n->left, level + 1);
printNode(n->right, level + 1);
}
int main() {
Node *n = new Node();
n->left = new Node();
n->right = new Node();
n->right->left = new Node();
n->right->right = new Node();
n->right->right->right = new Node();
computeHeight(n);
printNode(n);
}

Your mistake is on the following part and because of this you program exits without showing the error
if (n == NULL) {
n->height = 0;
}
When n is NULL; you should not try to access n->height. Replace it as follows and your code will work:
if (n == NULL) {
return;
}
Also, as the other answer mentioned, when you want to compute height recursively, you don't need a while loop just use the following recursive formula:
Height(n) = 1 + max(Height(n->left), Height(n->right))
Also, for consistency reasons usually the height of NULL subtree is defined to be -1. This allows the recursive formula to work properly.
Word of advice: In order to debug any program, an easy way is to just print messages before and after function calls and/or certain lines. This way by checking which messages are not printed, you can quickly pinpoint which functions/lines are causing a problem and then investigate them.

Related

g++ -O2 flag giving segmentation fault

The program below is a bst tree which works fine under unoptimized settings but produces a SIGSEGV under special circumstances. Since my debugging skills doesn't extend towards assembly, I can use some input to what is causing this error. Below is the full code so it can be reproduced. There is nothing fancy, a node struct is there to hold node data, a simple insert operation and a method to confirm the height of the tree.
#include <iostream>
#include <cstdlib>
using namespace std;
typedef struct avl_tree_node //node data
{
int data;
int balance{0};
avl_tree_node *left{NULL};
avl_tree_node *right{NULL};
avl_tree_node *parent{NULL};
}node;
class avl
{
private:
node *root;
int get_height(node *head) //calculates the height
{
if (head == NULL)
return -1;
int l_height = get_height(head->left);
int r_height = get_height(head->right);
if (l_height > r_height)
return l_height+1;
return r_height+1;
}
void unbalanced_insert(node *head, int item); //method definition for a simple insert
public:
avl(int data)
{
root->data = data;
root->parent = NULL;
root->left = NULL;
root->right = NULL;
}
int height() //gives the height
{
return get_height(root);
}
void unbalanced_insert(int item) //wrapper
{
unbalanced_insert(root, item);
}
};
void avl::unbalanced_insert(node *head, int item) //inserts node to the tree
{
//cout << "stepped" << endl;
if (item > head->data)
{
if (head->right == NULL)
{
head->right = (node*)malloc(sizeof(node));
head->right->data = item;
head->right->parent = head;
head->right->left = NULL;
head->right->right = NULL;
head->balance = 1;
return;
}
unbalanced_insert(head->right, item);
head->balance++;
return;
}
else
{
if (head->left == NULL)
{
head->left = (node*)malloc(sizeof(node));
head->left->data = item;
head->left->parent= head;
head->left->left = NULL;
head->left->right = NULL;
head->balance = -1;
return;
}
unbalanced_insert(head->left, item);
head->balance--;
return;
}
}
int main()
{
avl a(0);
for (int i = 1; i < 5; i++) //works until i < 4
{
a.unbalanced_insert(i);
}
cout << a.height() << endl;
return 0;
}
Under normal circumstances, I'd be happy that this works with unoptimized flags, but I have to build this with specific flags. One of such is the -O2 flag. The segmentation fault occurs between the avl a(0) object construction and the for loop inside main. The error also seems to be dependent on the boolean check of the for loop. This works fine if i < 4 and executed with: g++ avl.cpp -g -O2 -o program && ./program
One obvious problem, and it occurs on the very first function call in main, i.e. avl a(0):
root->data = data;
The root is uninitialized, thus the behavior is undefined.
I guess when instantiate the object of avl here.
avl a(0);
constructor of class as shown below is called.
avl(int data)
{
root->data = data;
root->parent = NULL;
root->left = NULL;
root->right = NULL;
}
But here I see root pointer is not allocated any memory

Remove max value from simply-connected list

How can I can remove max value from a Simply-Connected list?
Two of the solutions I tried produce wrong results. Please explain to me what am I doing wrong. With code, if not difficult.
Stack:
struct Stack
{
int info;
Stack *next;
} *top;
Wrong solution 1:
void delMaxValue(Stack **stck, int maxValue){
Stack *tmp = NULL;
do {
if ((*stck)->info != maxValue)
tmp = *stck;
cout << tmp->info << endl;
tmp = tmp->next;
*stck = (*stck)->next;
} while ((*stck)->next != NULL);
while (tmp != NULL)
{
*stck = tmp;
*stck = (*stck)->next;
tmp = tmp->next;
}
Wrong solution 2:
Stack* deleteMaxValue(Stack *begin) {
Stack *t = begin, *p = begin->next;
for (; p; p = p->next)
if (p->info > t->info) t = p;
p = begin;
if (p != t) {
while (p->next != t) p = p->next;
p->next = t->next;
}
else
begin = t->next;
delete t;
return begin;}
#include <cstdio>
#include <iostream>
struct Stack
{
int info;
Stack *next;
// added just to easy initialization
Stack(int _info, Stack *_next) : info(_info), next(_next) {}
} *top;
void delMaxValue(Stack *&head)
{
// first - find MaxValue in the list
// as you can see, i save pointer to the previous element in the list
Stack* max_prev = nullptr;
Stack* max = head;
for(Stack *i_prev = nullptr, *i = head; i; i_prev = i, i = i->next) {
if (max->info < i->info) {
max_prev = i_prev;
max = i;
}
}
// max has the maximum value and max_prev is the element before max in the list
// now we remove max
if (max_prev == nullptr) {
// max has no prev, so max is the head of the list. We assign the new head
head = max->next;
} else {
max_prev->next = max->next;
max->next = NULL;
}
}
void printStack(Stack *head) {
std::cout << "Priting " << head << std::endl;
for(Stack *i = head; i; i = i->next) {
std::cout << i << " " << i->info << std::endl;
}
}
int main()
{
Stack *head = new Stack(1, new Stack(15, new Stack(10, nullptr)));
printStack(head);
delMaxValue(head);
printStack(head);
return 0;
}
You may interest yourself in list helping macros from bsd, now available in glibc, newlib, openbsd etc., see here.
Your first solution takes maximum value as a parameter, while the second one doesn't. I am assuming we don't have the maximum value and will calculate it while processing the stack.
The basic approach should be to think of a logic first.
Step 1.) We need to pop all the elements to find the maximum element in the stack. Also, we need to store all the values we popped in another stack(say, auxiliary). Now, we are aware of the maximum value(say MAX).
Step 2.) Note we would have the stack in reverse now. Pop all elements from the auxiliary stack and if the value is not max, push them in the original stack.
Data Initially,
Original Stack: 1->2->3->4->100->5->7->NULL
Auxiliary Stack: NULL
Data after first Step,
Original Stack: NULL
Auxiliary Stack: 7->5->100->4->3->2->1->NULL
MAX: 100
Finally,
Original Stack: 1->2->3->4->5->7->NULL
Auxiliary Stack: NULL
Try to code for this. Your both solutions are doing things way differently than expected.
I hope It will be helpful.
#include <iostream>
struct LList
{
int info;
LList *next;
//constructer
LList(int info_) :info(info_) {
next = nullptr;
}
};
void removeMaxValue(LList *&root) {
int max = 0;
LList *temp = root;
//Searching for max value
while (temp!=nullptr)
{
if (temp->info > max)
max = temp->info;
temp = temp->next;
}
temp = root;
//Find max value and remove
while (temp->next->info != max)
temp = temp->next;
LList *maxNode = temp->next;
temp->next = temp->next->next;
delete maxNode;
}
void print(const LList *root)
{
while (root!=nullptr)
{
std::cout << root->info << " ";
root = root->next;
}
std::cout << std::endl;
}
int main() {
LList *root = new LList(15);
root->next= new LList(10);
root->next->next= new LList(45);
root->next->next->next = new LList(85);
root->next->next->next->next = new LList(5);
//before removing
print(root);
removeMaxValue(root);
//After removing
print(root);
std::cin.get();
}
Your two functions take two different approaches. I chose the one where the function doesn't know what actual max value is so it has to find it first.
First, the function just iterates through the elements and chooses the max value.
Then it searches for the first node that contains this value and removes the node.
void stackRemoveMaxValue(Stack*& top) {
if(top == nullptr) {
return;
}
// Find max value.
int maxValue = top->info;
Stack* node = top->next;
for(; node != nullptr; node = node->next) {
if(maxValue < node->info) {
maxValue = node->info;
}
}
// Remove first node that contains maxValue.
Stack* previous = nullptr;
Stack* current = top;
do {
if(current->info != maxValue) {
previous = current;
current = current->next;
} else {
if(previous != nullptr) {
previous->next = current->next;
} else {
top = current->next;
}
delete current;
return;
}
} while(current != nullptr);
}

Using an array of struct counting the number of occurrence of a word in a text file C++

Hi everyone this is my first time in Stackoverflow. I have a question regarding counting the occurrence of words in text file using C++. This is my code so far. I have to create an array struct of index of the word and the counter of each word then store all of them in an AVL tree. After opening the file and read a word, I look for it in the avl tree or trie. If it is there, use the node's index to increment the word's Cnt. If it is not there, add it to the word array and put its position in the next struct and put the structs position in the avl tree. Also I set the struct Cnt to 1. The problem I am having now is it seems like my program doesn't process the counting properly therefore it only prints out 0. Please give me recommendation on how I can fix the bug. Please find my code below:
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
#include <cstring>
#include <ctype.h>
#include <stdio.h>
#include <string>
#include <cctype>
#include <stdlib.h>
#include <stdbool.h>
using namespace std;
struct Node* insert(struct Node* node, int key) ;
void preOrder(struct Node *root) ;
void removePunct(char str[]);
int compareWord(char word1[], char word2[] );
struct Stats {
int wordPos, wordCnt;
};
Stats record[50000];
int indexRec = 0;
char word[50000*10] ;
int indexWord = 0;
int main() {
ifstream fin;
string fname;
char line[200], wordArray[500000];
cout << "Enter the text file name:" << endl;
cin >> fname;
fin.open(fname.c_str());
if (!fin) {
cerr << "Unable to open file" << endl;
exit(1);
}
struct Node *root = NULL;
while (!fin.eof() && fin >> line) { //use getline
for(int n=0,m=0; m!=strlen(line); m+=n) {
sscanf(&line[m],"%s%n",word,&n);
removePunct(word);
//strcpy(&wordArray[indexWord],word);
int flag = compareWord(wordArray, word);
if(flag==-1) {
strcpy(&wordArray[indexWord],word);
record[indexRec].wordPos = indexWord;
record[indexRec].wordCnt = 1;
root = insert(root, record[indexRec].wordPos);
indexWord+=strlen(word)+1;
// indexes of the word array
indexRec++;
cout << wordArray[indexWord] << " ";
} else
record[flag].wordCnt++;
cout << record[indexRec].wordCnt;
cout << endl;
}
/*for(int x = 0; x <= i; x++)
{
cout << record[x].wordPos << record[x].wordCnt << endl;
}*/
}
fin.close();
return 0;
}
void removePunct(char str[]) {
char *p;
int bad = 0;
int cur = 0;
while (str[cur] != '\0') {
if (bad < cur && !ispunct(str[cur]) && !isspace(str[cur])) {
str[bad] = str[cur];
}
if (ispunct(str[cur]) || isspace(str[cur])) {
cur++;
} else {
cur++;
bad++;
}
}
str[bad] = '\0';
for (p= str; *p!= '\0'; ++p) {
*p= tolower(*p);
}
return;
}
int compareWord(char word1[], char word2[] ) {
int x = strcmp(word1, word2);
if (x == 0 ) return x++;
if (x != 0) return -1;
}
struct Node {
int key;
struct Node *left;
struct Node *right;
int height;
};
// A utility function to get maximum of two integers
int max(int a, int b);
// A utility function to get height of the tree
int height(struct Node *N) {
if (N == NULL)
return 0;
return N->height;
}
// A utility function to get maximum of two integers
int max(int a, int b) {
return (a > b)? a : b;
}
/* Helper function that allocates a new node with the given key and
NULL left and right pointers. */
struct Node* newNode(int key) {
struct Node* node = (struct Node*)
malloc(sizeof(struct Node));
node->key = key;
node->left = NULL;
node->right = NULL;
node->height = 1; // new node is initially added at leaf
return(node);
}
// A utility function to right rotate subtree rooted with y
// See the diagram given above.
struct Node *rightRotate(struct Node *y) {
struct Node *x = y->left;
struct Node *T2 = x->right;
// Perform rotation
x->right = y;
y->left = T2;
// Update heights
y->height = max(height(y->left), height(y->right))+1;
x->height = max(height(x->left), height(x->right))+1;
// Return new root
return x;
}
// A utility function to left rotate subtree rooted with x
// See the diagram given above.
struct Node *leftRotate(struct Node *x) {
struct Node *y = x->right;
struct Node *T2 = y->left;
// Perform rotation
y->left = x;
x->right = T2;
// Update heights
x->height = max(height(x->left), height(x->right))+1;
y->height = max(height(y->left), height(y->right))+1;
// Return new root
return y;
}
// Get Balance factor of node N
int getBalance(struct Node *N) {
if (N == NULL)
return 0;
return height(N->left) - height(N->right);
}
// Recursive function to insert key in subtree rooted
// with node and returns new root of subtree.
struct Node* insert(struct Node* node, int key) {
/* 1. Perform the normal BST insertion */
if (node == NULL)
return(newNode(key));
if (key < node->key)
node->left = insert(node->left, key);
else if (key > node->key)
node->right = insert(node->right, key);
else // Equal keys are not allowed in BST
return node;
/* 2. Update height of this ancestor node */
node->height = 1 + max(height(node->left),
height(node->right));
/* 3. Get the balance factor of this ancestor
node to check whether this node became
unbalanced */
int balance = getBalance(node);
// If this node becomes unbalanced, then
// there are 4 cases
// Left Left Case
if (balance > 1 && key < node->left->key)
return rightRotate(node);
// Right Right Case
if (balance < -1 && key > node->right->key)
return leftRotate(node);
// Left Right Case
if (balance > 1 && key > node->left->key) {
node->left = leftRotate(node->left);
return rightRotate(node);
}
// Right Left Case
if (balance < -1 && key < node->right->key) {
node->right = rightRotate(node->right);
return leftRotate(node);
}
/* return the (unchanged) node pointer */
return node;
}
void preOrder(struct Node *root) {
if(root != NULL) {
printf("%d ", root->key);
preOrder(root->left);
preOrder(root->right);
}
}
One problem (I cannot see if this is the only problem) is that you have code like this, deleting all the intermediate lines:
record[indexRec].wordCnt = 1;
if find word fails
indexRec++;
cout << record[indexRec].wordCnt;
So when you have a new word (if I understand the code correctly!) you are printing out the next record. One fix would be:
if (flag==-1)
cout << record[indexRec-1].wordCnt;
else
cout << record[indexRec].wordCnt;
There's a lot of other issues, like compareWord() is very wrong, you should decide if you really want to use C++ or just C with std::cout, the file reading code is odd, you're including both C and C++ versions of standard headers, etc, but these are issues for another question!

Converting a Binary Tree to Double Threaded Binary Tree?

I could not find anything on search to satisfy my question, if it exists, I'm sorry!
I am working on a college assignment about threaded binary trees. I.e. various kinds of traversals - inorder, postorder and preorder on double TBT.
This is the TBTNode struct:
struct TBTNode {
TBTNode *left, *right, *parent;
char data;
bool left_normal, right_normal;
TBTNode(char d) {
data = d;
left = NULL;
right = NULL;
parent = NULL;
left_normal = true;
right_normal = true;
}
};
As you can see, there is not much distinction between a Binary Tree node and a TBT node, except that the node's properties, viz. {left,right}_normal are set to true when required.
To create the tree, I have this:
class TBT {
TBTNode *root;
public:
TBT() {
root = new TBTNode(0);
root->right = root;
root->right_normal = true;
cout << "Root:" ;
root->left = create();
if(root->left)
root->left_normal = true;
}
TBTNode* create();
};
TBTNode* TBT::create() {
char data;
TBTNode *node = NULL;
cout << endl << "Enter data (0 to quit): ";
cin >> data;
if(data == '0')
return NULL;
node = new TBTNode(data);
cout << endl << "Enter left child of " << data;
node->left = create();
if(node->left)
node->left->parent = node;
else {
node->left = root;
node->right = node->parent;
node->left_normal = node->right_normal = false;
}
cout << endl << "Enter right child of " << data;
node->right = create();
if(node->right)
node->right->parent = node;
else {
node->left = node;
node->right = node->parent->parent;
node->left_normal = node->right_normal = false;
}
return node;
}
After the tree gets recursively created using the above code, I want to convert it into a double threaded binary tree. I know the concept that left child is linked to the child's inorder predecessor and right to inorder successor, but I am unable to create an algorithm. Can someone help me?
I found the solution myself. First traverse the tree in inorder and add nodes to an array as you go on. Then process the array to link threads, because for a given element x in the array, the one previous to x will be inorder predecessor and one after x will be inorder successor. For the first and last element, special checks are made to link them to the head node (not root).
Parent link isn't needed, and it's removed.
Code is as follows:
class TBT {
TBTNode *root;
void createInorderArray(TBTNode *T);
TBTNode **array;
unsigned array_size;
public:
TBT();
TBTNode* create();
void inorder();
void preorder();
};
TBT::TBT() {
root = new TBTNode(0);
root->right = root;
root->right_normal = true;
cout << "Root:" ;
root->left = create();
if(!root->left) {
root->left_normal = false;
root->left = root;
}
array = NULL;
array_size = 0;
createInorderArray(root->left);
for(unsigned i = 0; i < array_size; i++) {
if(!array[i]->left) {
array[i]->left = i == 0 ? root : array[i-1];
array[i]->left_normal = false;
}
if(!array[i]->right) {
array[i]->right_normal = false;
array[i]->right = i == (array_size - 1) ? root : array[i+1];
}
}
free(array);
array_size = 0;
}
void TBT::createInorderArray(TBTNode *T) {
if(!T)
return;
createInorderArray(T->left);
array = (TBTNode**) realloc(array, sizeof(TBTNode**) * ++array_size);
array[array_size-1] = T;
createInorderArray(T->right);
}

Binary Search Tree not working properly? (parse errors)

I'm getting parse errors in my code. I'm probably missing something silly.. but after staring at it, I can't figure out what's wrong. The errors start at line 26:
BinaryTree.cpp:26: parse error before 'new
BinaryTree.cpp:31: parse error before ';'
....etc etc... any ideas?
#include <cstdlib>
#include <iostream>
using namespace std;
class BinaryTree{
struct node{
int data;
node *left;
node *right;
};
node *root;
public:
BinaryTree(int);
void addNode(int);
void inorder();
void printInorder(node);
int getHeight();
int height(node);
};
BinaryTree::BinaryTree(int data){
node *new = new node;
new->data = data;
new->left = NULL;
new->right = NULL;
root = new;
}
void BinaryTree::addNode(int data){
node *new = new node;
new->data = data;
new->left = NULL;
new->right = NULL;
node *current;
node *parent = NULL;
current = root;
while(current){
parent = current;
if(new->data > current->data) current = current->right;
else current = current->left;
}
if(new->data < parent->data) parent->left = new;
else parent->right = new;
}
void BinaryTree::inorder()
printInorder(root);
}
void BinaryTree::printInorder(node current){
if(current != NULL){
if(tree->left) printInorder(tree->left);
cout<<" "<<tree->data<<" ";
if(tree->right) printInorder(tree->right);
}
else return;
}
int BinaryTree::getHeight(){
return height(root);
}
int BinaryTree::height(node new){
if (new == NULL) return 0;
else return max(height(new->left), height(new->right)) + 1;
}
int main(int argCount, char *argVal[]){
int number = atoi(argVal[1]);
BinaryTree myTree = new BinaryTree(number);
for(int i=2; i <= argCount; i++){
number = atoi(argVal[i]);
myTree.addNode(number);
}
myTree.inorder();
int height = myTree.getHeight();
cout << endl << "height = " << height << endl;
return 0;
}
new is a C++ keyword. You mustn't use it as an identifier (e.g. variable name).
In any event, your constructor would be better off as:
BinaryTree::BinaryTree(int data) : root(new node) { /* ... */ }
And your class as a whole would probably be better off with unique_ptr<Node>s.
new is keyword in c++ and You can't name variable with that word so
node *new = new node;
is illegal
new is a reserved word, you cannot use it as a variable name.