How to reroot a tree which is allocated through malloc() - c++

Below is a program which first build Binary tree from inorder and preorder and then find the node which contain largest balanced tree.
My both function for Buildtree and IsBalanced is right.
I am reading inorder and preorder from input.txt file; so in first iteration my program is showing correct output, but in the second iteration, it is not working.
I think that there is problem in deleting root.
After running above program you will get which problem I am talking about :
/* Tree - Program to find largest Balanced tree in given tree
#Date : 15 July 2012
This program works only for one input sample
*/
#include<stdio.h>
#include<stdlib.h>
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
using namespace std;
struct node
{
char data;
struct node* left;
struct node* right;
};
/* Prototypes for utility functions */
int search(string arr, int strt, int end, char value);
struct node* newNode(char data);
int isBalanced(struct node *root, int* height,int *max_size_ref, bool *is_bal_ref,char *val)
{
/* lh = Height of left subtree ,rh = Height of right subtree */
int lh = 0, rh = 0;
int left_flag=0;
int right_flag=0;
/* l will be true if left subtree is balanced
and r will be true if right subtree is balanced */
int l = 0, r = 0;
if(root == NULL)
{
*height = 0;
*is_bal_ref = 1;
return 0;
}
l = isBalanced(root->left, &lh, max_size_ref,is_bal_ref, val);
if (*is_bal_ref == 1)
left_flag=true;
r = isBalanced(root->right,&rh, max_size_ref,is_bal_ref, val);
if (*is_bal_ref == 1)
right_flag = true;
*height = (lh > rh? lh: rh) + 1;
if((lh - rh >= 2) || (rh - lh >= 2))
*is_bal_ref= 0;
/* If this node is balanced and left and right subtrees
are balanced then return true */
if(left_flag && right_flag && *is_bal_ref ){
*is_bal_ref= 1;
if (l + r + 1 > *max_size_ref)
{
*max_size_ref = l + r+ 1;
*val = root->data;}
return l + r + 1;
}
else
{
//Since this subtree is not Balanced, set is_bal flag for parent calls
*is_bal_ref = 0;
return 0;
}
}
struct node* buildTree(string in, string pre, int inStrt, int inEnd)
{
static int preIndex = 0;
if(inStrt > inEnd)
return NULL;
/* Pick current node from Preorder traversal using preIndex
and increment preIndex */
struct node *tNode = newNode(pre[preIndex++]);
/* If this node has no children then return */
if(inStrt == inEnd)
return tNode;
int inIndex = search(in, inStrt, inEnd, tNode->data);
/* Using index in Inorder traversal, construct left and
right subtress */
tNode->left = buildTree(in, pre, inStrt, inIndex-1);
tNode->right = buildTree(in, pre, inIndex+1, inEnd);
return tNode;
}
/* Function to find index of value in arr[start...end]
The function assumes that value is present in in[] */
int search(string arr, int strt, int end, char value)
{
int i;
for(i = strt; i <= end; i++)
{
if(arr[i] == value)
return i;
}
}
/* Helper function */
struct node* newNode(char data)
{
struct node* node = new (struct node);
node->data = data;
node->left = NULL;
node->right = NULL;
return(node);
}
/* This function is for inorder traversal */
void printInorder(struct node* node)
{
if (node == NULL)
return;
printInorder(node->left);
printf("%c ", node->data);
printInorder(node->right);
}
// function to free binary tree
void freeT(struct node* t ) //get root
{
if( t == NULL )
return;
if( t->left != NULL )
freeT( t->left );
if( t->right != NULL )
freeT( t->right);
delete(t); /* free(t) if c */
return;
}
/* Driver program to test above functions */
int main()
{
string line , inorder;
ifstream myfile ("input.txt");
ofstream myofile ("output.txt" );
if (myfile.is_open())
{
int len=0;
char data=NULL;
int height=0;
int max_size_ref=0;
bool is=false;
int size=0;
struct node *root = NULL;
while ( myfile.good() )
{
getline (myfile,line);
//cout << line << endl;
inorder=line;
getline (myfile,line);
//cout << line << endl;
len = line.size();
//cout<<"len="<<len;
root= buildTree(inorder, line, 0, len - 1);
data=NULL;
height=0;
max_size_ref=0;
is=false;
size=isBalanced(root, &height ,&max_size_ref, &is, &data);
if(data!=NULL)
{
myofile<<data;
myofile<<"\n";
//std::cout<<data;
}
else
{
myofile<<-1;
myofile<<"\n";
}
//printf("\n Inorder traversal of the constructed tree is \n");
//printInorder(root);
getchar();
//freeT(root);
//root=NULL;
}
myfile.close();
myofile.close();
}
//getchar();
return 0;
}
First run this program with input.txt containing below content and see output.txt
FDBGEHAC
ABDFEGHC
Then run above program with
FDBGEHAC
ABDFEGHC
FDCEBAJHGI
ABCDFEGHJI
Now see output.txt
You will get what I really want.

When using a tree or hierarchical structure ( collection ), you should keep the "root" variable, outside of the "while" loop, or other nodes.
This is a pseudocode, not intended to be full valid code, just an example:
int main()
{
...
struct node *root = NULL;
while ( myfile.good() )
{
// load tree, maybe change root
} // while
...
} // int main()
As you already check. "Root" is a pointer to an structure, and even that may change which node is root, you should have an external variable.

It seems you have a bug in buildTree that is triggered by the 2nd set of data. The bug causes infinite recursion, you get a "stackoverflow" :-) and your program crashes. You can confirm this by swapping lines 3 and 4 with lines 1 and 2 of the second input.txt sample data, your program will then die on the first iteration. You can run your program with gdb and will catch the stackoverflow. You can also put a print statement in buildTree and will see that it gets caught in infinite recursion.

Related

How can I delete the k-th smallest element in balanced bst

I have to delete the k-th smallest element in a balanced bst. The code works in most cases, but when i try to delete the root it breaks connections between nodes and it prints a partially remaining bbst. When i try to delete an interior node or a leaf node it works.
This is the code:
#include <iostream>
using namespace std;
struct arbore_binar {
int key;
struct arbore_binar* left;
struct arbore_binar* right;
int size = 0;
};
arbore_binar* nod_arbore(int key) {
arbore_binar* node = (arbore_binar*)malloc(sizeof(arbore_binar));
node->key = key;
node->left = NULL;
node->right = NULL;
return node;
}
struct arbore_binar* Build_Tree(int a[], int i, int j, int size) {
if (i > j)
{
return NULL;
size = 0;
}
int m = (i + j) / 2;
arbore_binar* rad = nod_arbore(a[m]);
rad->left = Build_Tree(a, i, m - 1, size+1);
rad->right = Build_Tree(a, m + 1, j, size+1);
if ((rad->right) && (rad->left))
rad->size = rad->right->size + 1 + rad->left->size;
else
rad->size = size;
if ((!rad->left) && (!rad->right))
rad->size = 1;
//printf("%d %d \n",rad->key, rad->size);
return rad;
}
void postorder(arbore_binar* p, int indent = 0)
{
if (p != NULL) {
if (indent) {
std::cout <<std::string(indent, ' ') ;
}
cout << p->key << endl;
if (p->left) postorder(p->left, indent + 4);
if (p->right) postorder(p->right, indent + 4);
}
}
struct arbore_binar* OS_SELECT(arbore_binar* rad, int poz) {
if (poz == 0)
return NULL;
int r = 1;
if (!rad)
return NULL;
if(rad->left)
r= rad->left->size + 1;
if (poz == r)
return rad;
else if (poz < r && rad->left)
return OS_SELECT(rad->left, poz);
else
{
if(rad->right)
return OS_SELECT(rad->right, poz - r);
}
}
struct arbore_binar* succesor(arbore_binar* rad) {
struct arbore_binar* current = rad;
while (current && current->left != NULL)
current = current->left;
return current;
}
struct arbore_binar* OS_DELETE(arbore_binar* rad, int poz) {
if (poz == 0)
return NULL;
int r = 1;
if (!rad)
return NULL;
if (rad->left) {
r = rad->left->size + 1;
}
if (poz < r && rad->left) {
rad->left = OS_DELETE(rad->left, poz);
return rad;
}
else if(poz>r && rad->right)
{
rad->right= OS_DELETE(rad->right, poz - r);
return rad;
}
if (!rad->left)
{
arbore_binar* actual = rad->right;
free(rad);
return actual;
}
else if (!rad->right) {
arbore_binar* actual = rad->left;
free(rad);
return actual;
}
else {
arbore_binar* parinte = rad;
arbore_binar* actual = succesor(rad->right);
if (parinte != rad)
parinte->left = actual->right;
else
parinte->right = actual->right;
rad->key=actual->key;
free(actual);
return rad;
}
}
void demo() {
int array[] = { 1,2,3,4,5,6,7,8,9,10,11 };
arbore_binar* rad = Build_Tree(array, 0, 10, 0);
postorder(rad);
printf("\n");
printf("%d \n", rad->size);
arbore_binar* cautat = nod_arbore(0);
cautat = OS_SELECT(rad, 5);
if (cautat)
printf("Elementul de gasit este: %d \n", cautat->key);
else printf("Prea mic arbore\n");
printf("\n");
cautat = OS_DELETE(rad, 6);
if (cautat)
printf("Elementul de sters este: %d \n", cautat->key);
else printf("Prea mic arbore\n");
printf("\n");
postorder(rad);
}
int main()
{
demo();
}
The code prints this:
6
3
1
2
4
5
9
7
8
10
11
11
Elementul de gasit este: 5
Elementul de sters este: 7
7
3
1
2
4
5
8
But it can be clearly seen that it breaks the connection to 9 and so it does not print correctly. What can I do to improve it?
I will not write a code. I know you can manage it yourself. Just try to explain the way nodes are deleted from the BST. There are three basic cases:
If node is a leaf (does not have children) just delete the node
If node has one child, than the node is deleted, and its child comes to its place
If node has two children, than go to the left child of the node you are deleting. After that go right as far as you can. Delete node you are in (it can have at most one child) using case 1 or 2, and the label of deleted node write in the node you needed to delete.
There is a alternative for 3: you can go to the left child of the node, and than go left as far as you can.
Anyhow, I dont know what do you mean when talking about balanced BST. The tree you are building in the program is not a balanced BST. Balanced BSTs are AVL tree and red-black tree, and algorithms for insertion and deletion for them are, although basically the same, should contain balancing of the tree.
If I understand what you are doing, you use divide and conquer to build up the tree from sorted array. I have to point out that, if you have sorted array, no BST is needed. You can use binary search which will search array even faster that you can do in the BST. In fact, you will have the algorithm with the same complexity: O(lg n), but you will not need to build BST. The idea of BST is to speed up search in average if you have random array. For random array the average complexity of the search would be O(lg n), and worst-case still O(n). But if you use balanced BST (namely AVL or red-black tree), you will have worst-case search of complexity O(lg n).
You can do an inorder traversal and count (down) the number of nodes you visited.
#include <iostream>
#include <array>
#include <functional>
#include <type_traits>
using namespace std;
template<typename Data>
struct Node {
Data data;
Node *left = nullptr, *right = nullptr;
Node(const Data& data) : data(data) {}
};
//template <typename Node>
//using Func = std::function<void(const Node *)>;
template<typename Node, typename preFunc = std::nullptr_t, typename inFunc = std::nullptr_t, typename postFunc = std::nullptr_t>
void Order(Node *root, preFunc pre = nullptr, inFunc in = nullptr, postFunc post = nullptr) {
if constexpr (!std::is_same<preFunc, std::nullptr_t>::value)
pre(root);
if (root->left != nullptr) Order(root->left, pre, in, post); //traverse left if exists
if constexpr (!std::is_same<inFunc, std::nullptr_t>::value)
in(root);
if (root->right != nullptr) Order(root->right, pre, in, post);//traverse right if exists
if constexpr (!std::is_same<postFunc, std::nullptr_t>::value)
post(root);
}
int main() {
std::array<Node<int>, 3> nodes { { { 2 }, { 1 }, { 3 } } };
nodes[0].left = &nodes[1];
nodes[0].right = &nodes[2];
int cnt = 3;
Node<int> *kth = nullptr;
Order(&nodes[0],
nullptr, // [](const Node<int> * node) { std::cout << "Pre:" << node->data << '\n'; },
[&cnt, &kth](Node<int> * node) mutable { if (!--cnt) kth = node; }
//, nullptr// [](const Node<int> * node) { std::cout << "Post:" << node->data << '\n'; }
);
if (kth) {
std::cout << kth->data << '\n';
// delete kth
}
return 0;
}
This is unfortunately O(N) always, you could plaster the Order function with early out flags or misuse throw to stop early.
See this why tail recursion is ... difficult for this.

How to count the occurence of each word in multiple text files

I want to count the occurence of each word in a bunch of texts.
I'm able to count each word and its occurence in one text ( I insert each word in the text in the binary tree and increment it by one whenver I find it again in the text) but I can't count each word in all texts.
Silly example:
text 1: hello adam, my name is adam I want to be happy.
text 2: hello sam, where is he from ?
(each word occurence in one text) Tree1: adam,2 hello,1 my,1 name,1 is,1 I,1 want,1 to,1 be,1 happy,1
(each word occurence in all texts) Tree2: hello,2 adam,1 sam,1 where,1 is,2 ...
Can someone explain to me what can I do ? or help me make an algorithm that does this?
My files:
Node.hpp
class Node{
private:
Node *left; //left child
Node *right; //right child
std::string num;
public:
int data; //number
Node(); //constructor
void setData(string num, int data); //sets number in node
string getData(); //return numbers from node
int &getOcc();
void setLeft(Node *l); //sets left child pointer
Node* &getLeft(); //returns left child pointer
void setRight(Node *r); //sets right child pointer
Node* &getRight(); //return right child pointer
};
Node.cpp
Node::Node(){
this->left = NULL;
this->right = NULL;
}
void Node::setData(string num, int data){
this->num = num;
this->data = data;
}
string Node::getData(){
return this->num;
}
int &Node::getOcc(){
return this->data;
}
void Node::setLeft(Node *l){
this->left = l;
}
Node* &Node::getLeft(){
return this->left;
}
void Node::setRight(Node *r){
this->right = r;
}
Node* &Node::getRight(){
return this->right;
}
BST.hpp
//BST class
class BST{
private:
Node * root; //root node pointer
public:
BST(); //constructor
~BST(); //destructor
void Insert(string num, int data); //Inserts new number in tree
void InsertIDF(string num, int data); //Inserts new number in tree
bool find(string num); //finds whether a number is present in tree
void min(); //find and print minimum number in the tree
void max(); //find and print maximum number in the tree
void save_file(string filename); //save the tree to file
void Delete(string num); //deletes a number from tree
void LoadFromFile(string filename); //loads numbers from file to tree
void Print(); //print tree to stdout
//private functions used as helper functions in the public operations
private:
void printHelper(Node *root);
bool findHelper(Node *root,string num);
void InsertHelper(Node * &current, string num, int data);
void InsertHelperIDF(Node * &current, string num, int data);
void findMinHelper(Node* current);
void findMaxHelper(Node * current);
void saveHelper(ofstream &fout, Node* current);
Node* DeleteHelper(Node *current, string num);
Node * findMaximum(Node * n);
void clear(Node *currnt);
};
BST.cpp
BST::BST(){
this->root = NULL; //root is NULL in the start
}
BST::~BST(){
clear(root); //delete all nodes
}
void BST::clear(Node* current){
if(current == NULL)
return;
clear(current->getLeft()); //clear left subtree
clear(current->getRight()); //clear right subtree
delete current; //delete this node
}
void BST::Insert(string num, int data){
InsertHelper(root,num,data); //call helper to insert
}
void BST::InsertHelper( Node * &current, string num, int data ){
if ( current == nullptr ){
// create new node to be inserted
current = new Node();
current->setData( num, data );
current->setLeft( nullptr );
current->setRight( nullptr );
} else if ( num < current->getData() ){
InsertHelper( current->getLeft(), num, data );
} else if ( current->getData() < num ){
InsertHelper( current->getRight(), num, data );
} else {
int h = current->getOcc();
h++;
current->setData(num, h);
}
}
void BST::InsertIDF(string num, int data){
InsertHelperIDF(root,num,data); //call helper to insert
}
void BST::InsertHelperIDF( Node * &current, string num, int data){
if ( current == nullptr ){
// create new node to be inserted
current = new Node();
current->setData( num, data );
current->setLeft( nullptr );
current->setRight( nullptr );
} else if ( num < current->getData() ){
InsertHelperIDF( current->getLeft(), num, data );
} else if ( current->getData() < num ){
InsertHelperIDF( current->getRight(), num, data );
}
}
void BST::min(){
findMinHelper(root);
}
void BST::findMinHelper(Node* current){
if(current == NULL)
return;
if(current->getLeft() == NULL) //if no node at right
cout<<current->getData(); //current has min data
else
findMinHelper(current->getLeft()); //check on left subtree
}
void BST::max(){
findMaxHelper(root);
}
void BST::findMaxHelper(Node * current){
if(current == NULL)
return;
if(current->getRight() == NULL) //if no node at right
cout<<current->getData(); //current node has max data
else
findMaxHelper(current->getRight()); //check on right subtree
}
void BST::Print(){
printHelper(root);
}
void BST::printHelper(Node *current){
if(current == NULL) //stop if NULL
return;
printHelper(current->getLeft()); //print left tree
cout<<current->getData() << " " << current->getOcc() << " "; //print current node data
printHelper(current->getRight()); //print right tree
}
void BST::Delete(string num){
root = DeleteHelper(root,num);
}
Node* BST::DeleteHelper(Node *current, string num){
if(current == NULL)
return NULL;
Node *tobeReturned;
if (current->getData() == num) { //if key is found
if (current->getLeft() == NULL) { //no node at left
tobeReturned = current->getRight();
delete current;
return tobeReturned; //right subtree should replace this node
} else if (current->getRight() == NULL) {
tobeReturned = current->getLeft();
delete current;
return tobeReturned;
} else {
//find maximum node in the left subtree
Node * maxnode = findMaximum(current->getLeft());
//copy values from max node to this node
// current->setData(maxnode->getData());
//delete the max node
current->setLeft(DeleteHelper(current->getLeft(), num));
}
cout<<"Deleted!!!";
} else { //not found
if (num < current->getData()) {
current->setLeft(DeleteHelper(current->getLeft(),num));
} else {
current->setRight(DeleteHelper(current->getRight(), num));
}
}
return current;
}
Node* BST::findMaximum(Node * n){
if(n->getRight() == NULL) //if no node at right, current is maximum
return n;
return findMaximum(n->getRight()); //find in right subtree
}
this is my main.cpp
int x = 0;
// go through each story
for( Histoire * histoire : * histoires ) {
// go through each sentence
for( Phrase p : * histoire ) {
// go through each word
for ( Phrase w : p ){
std::stringstream sstream;
sstream << w;
std::string s = sstream.str();
tree.Insert(s , 1); // here i insert each word in a tree and count its occurence in one text
}
// treeIDF.Insert(t,1);
};
Well it indeed seems like a homework :)
You sure binary tree is appropriate data structure for such problem? As suggested in comments, best would be to simply use std::map.
#include <fstream>
#include <iostream>
#include <map>
#include <string>
#include <vector>
void processFile(const std::string &filename,
std::map<std::string, int> &words_count) {
std::string word;
std::ifstream load_file;
load_file.open(filename.c_str(), std::ifstream::in);
while (load_file >> word) {
if (words_count.find(word) == words_count.end()) {
words_count[word] = 1;
} else {
words_count[word]++;
}
}
}
int main() {
const std::vector<std::string> files_to_process{"text1.txt", "text2.txt"};
std::map<std::string, int> words_count{};
for (const auto &file : files_to_process) {
processFile(file, words_count);
}
for (const auto &w : words_count) {
std::cout << w.first << " " << w.second << std::endl;
}
}
This has to be refined, though - like get rid of special characters, pack it into class etc. If you can't use STL (for whatever reason), simply create a key-value structure yourself and implement some search.

Code::Blocks: Cannot open file: ../libgcc/unwind-sjlj.c

I've been working on this project for a bit now and I'm running into this issue that I can't solve.
As a preface, the program builds a binary tree from data from a file, then the tree can grow, and the new complete information is written over that original file.
To do this all with a single information vector, I'm having my input vector be ordered in level order, however (as far as I understand, please correct me if I'm wrong), in order to do this, I need to have the NULL spaces accounted for in my vector, and to rewrite everything correctly I need faux-NULL (nodes that fill space but don't contain any actual information other than pointers) nodes on my tree.
When the tree grows, then, I'm trying to complete and balance it with "NULL" nodes, and I do so recursively with an in-order traversal and the depth in mind. When I run this, however, I'm getting a Segmentation Fault, and when I run it step by step with the debugger, I'm getting
Cannot open file: ../../../../../src/gcc-4.9.2/libgcc/unwind-sjlj.c
specifically. It occurs when, during the recursive traversal, the algorithm adds a node, and upon reaching the "return" portion of the node's memory allocator, the error pops up and the program breaks.
Is this an error with my code or is it an error with Code::Blocks' libraries?
Relevant code:
struct Node
{
int idx; //idx is information relevant to the program but not to the structure
std::string phrase;
Node* left, * right;
};
Node* newNode(std::string data, int idx) //memory allocator
{
Node* node = new Node;
node->phrase = data;
node->idx = idx;
node->left = node->right = NULL;
return (node); //right here is where the debugger gives me the error
}
// Function to insert nodes in level order
Node* insertLevelOrder(std::string arr[], int idx[], Node* root,int i, int n)
{
// Base case for recursion
if (i < n)
{
Node* temp = newNode(arr[i],idx[i]);
root = temp;
// insert left child
root->left = insertLevelOrder(arr,idx,root->left, 2 * i + 1, n);
// insert right child
root->right = insertLevelOrder(arr,idx,root->right, 2 * i + 2, n);
}
return root;
}
int calcularProfundidad(Node * root) //Sorry for the spanglish--this is "calculateDepth"
{
if (root == NULL)
{
return 0;
}
int h1 = calcularProfundidad(root->left); //recursively calculate depth of left subtree
int h2 = calcularProfundidad(root->right); //and of right subtree
return 1 + max(h1,h2);
}
void rellenarNulos(Node * root, int prof, int counter) //fills "empty spaces" with "faux-NULL" nodes
{
if(counter == prof) //if reaches depth, stops, if not, adds more nodes
return;
if(root->left == NULL && counter < prof)
{
Node * auxNode = newNode("NULL",0); //error in this call
root->left = auxNode;
}
if(root->right == NULL && counter < prof)
{
Node * auxNode2 = newNode("NULL",0);
root->right = auxNode2;
}
rellenarNulos(root->left,prof,counter++);
rellenarNulos(root->right,prof,counter++);
}
#include <iostream>
#include <fstream>
#include <string>
#include "arbLib.hpp"
using namespace std;
int main()
{
//Builds tree from file
int N;
fstream myfile ("test.txt");
if (!myfile.is_open())
{
cout << "Unable to open file" << endl;
return 0;
}
myfile >> N; //N is the number of nodes
string words[N];
for(int i=0;i<N;i++)
myfile >> words[i];
int nums[N];
for(int j=0;j<N;j++)
myfile >> nums[j];
myfile.close();
//Builds tree from these vectors that are level order
Node *root = insertLevelOrder(words,nums,root,0,N);
int prof = calcularProfundidad(root); //calculates depth
rellenarNulos(root,prof,1); //here is where the program dies
inOrder(root);
destroyTree(root);
cout << endl;
return 0;
}

Function couldn't been resolved

I have a problem with my C++ code. It says that the all the functions starting with isPerfectRec() couldn't be resolved...Why? I tried a lot of things but apparently they don't work. I have a lot of assigments like to verify if the binary search tree is perfect, to find the second largest element in a binary search tree and so on..
#include <stdio.h>
#include<iostream>
#include<stack>
template<typename T> class BinarySearchTree {
public:
BinarySearchTree<T> *root, *left_son, *right_son, *parent;
T *pinfo;
BinarySearchTree() {
left_son = right_son = NULL;
root = this;
pinfo = NULL;
}
void setInfo(T info) {
pinfo = new T;
*pinfo = info;
}
void insert(T x) {
if (pinfo == NULL)
setInfo(x);
else
insert_rec(x);
}
bool isPerfectRec(BinarySearchTree *root, int d, int level = 0)
{
// An empty tree is perfect
if (*root == NULL)
return true;
// If leaf node, then its depth must be same as
// depth of all other leaves.
if (*root->left_son == NULL && root->*right_son == NULL)
return (d == level+1);
// If internal node and one child is empty
if (root->*left_son == NULL || root->*right_son == NULL)
return false;
// Left and right subtrees must be perfect.
return isPerfectRec(root->*left_son, d, level+1) &&
isPerfectRec(root->*right_son, d, level+1);
}
// Wrapper over isPerfectRec()
bool isPerfect(BinarySearchTree *root)
{
int d = findADepth(root);
return isPerfectRec(root, d);
}
int findADepth(BinarySearchTree *node)
{
int d = 0;
while (node != NULL)
{
d++;
node = node->left_son;
}
return d;
}
// A function to find 2nd largest element in a given tree.
void secondLargestUtil(BinarySearchTree *root, int &c)
{
// Base cases, the second condition is important to
// avoid unnecessary recursive calls
if (root == NULL || c >= 2)
return;
// Follow reverse inorder traversal so that the
// largest element is visited first
secondLargestUtil(root->right_son, c);
// Increment count of visited nodes
c++;
// If c becomes k now, then this is the 2nd largest
if (c == 2)
{
std::cout << "2nd largest element is "
<< root->pinfo;
printf("\n___\n");
return;
}
// Recur for left subtree
secondLargestUtil(root->left_son, c);
}
void secondLargest(BinarySearchTree *root)
{
// Initialize count of nodes visited as 0
int c = 0;
// Note that c is passed by reference
secondLargestUtil(root, c);
}
bool hasOnlyOneChild(int pre[], int size)
{
int nextDiff, lastDiff;
for (int i=0; i<size-1; i++)
{
nextDiff = pre[i] - pre[i+1];
lastDiff = pre[i] - pre[size-1];
if (nextDiff*lastDiff < 0)
return false;;
}
return true;
}
BinarySearchTree * readListInter(){
BinarySearchTree* root = NULL;//returning object
BinarySearchTree* temp;
BinarySearchTree* input;//new node to add
int x;
std::cout << "enter number (>0 to stop): ";
std::cin >> x;
while(x>=0){
input = BinarySearchTree(x);
if(root == NULL){//if root is empty
root = input;
temp = root;//temp is use to store value for compare
}
else{
temp = root; //for each new addition, must start at root to find correct spot
while(input != NULL){
if( x < temp->pinfo){//if smaller x to add to left
if(temp->left_son == NULL){//left is empty
temp->left_son = input;
input = NULL;//new node added, exit the loop
}
else{//if not empty set temp to subtree
temp = temp->left_son;//need to move left from the current position
}
}
else{//otherwise x add to right
if(temp->right_son == NULL){//right is empty
temp->right_son = input;
input = NULL;//new node added, exit the loop
}
else{
temp = temp->right_son;//need to move right from the current position
}
}
}
}
std::cin >> x;
}
return root;
}
};
int main() {
BinarySearchTree<int> *r = new BinarySearchTree<int>;
BinarySearchTree<int> *r1 = new BinarySearchTree<int>;
BinarySearchTree<int> *p = new BinarySearchTree<int>;
p = readListInter();
r->insert(6);
r->insert(8);
r->insert(1);
r->insert(9);
r->insert(10);
r->insert(4);
r->insert(13);
r->insert(12);
printf("\n___\n");
r1->insert(6);
r1->insert(8);
r1->insert(1);
r1->insert(9);
r1->insert(10);
r1->insert(4);
r1->insert(13);
r1->insert(12);
printf("\n___\n");
r->isPerfect(r);
int pre[] = {8, 3, 5, 7, 6};
int size = sizeof(pre)/sizeof(pre[0]);
if (hasOnlyOneChild(pre, size) == true )
printf("Yes");
else
printf("No");
s
return 0;
}
I think you need to write BinarySearchTree<T> instead of BinarySearchTree as a datatype in those functions.

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!