I have a program where I have a binary tree, represented as a structure with two pointers and a root. I then want to enter n elements (denoted by the br variable) as values of the nodes of the tree. Then I enter these elements using the add(param1,...) function. However when I press return key, after I have entered all of them, the program crashes. I would like to ask why this happens?
// TreeGraph.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
using namespace std;
struct elem {
char key;
elem *left, *right;
} *root = NULL;
void add(int n, elem * &t);
int num,br,i;
int main()
{
cout << "Въведете брой елементи\n";
cin >> br;
cout << "Въведете стойнсотите на листата на дървото\n";
while (i != br) {
cin >> num;
add(num, root);
i++;
}
return 0;
}
void add(int n, elem * &t) {
if (t) {
t = new elem;
t->key = n;
t->left = t->right = NULL;
}
else {
if (t->key < n)
add(n, t->right);
else
add(n, t->left);
}
}
The problem is not an infinite loop. You are dereferencing a null pointer, so the program crashes.
In this code:
void add(int n, elem * &t) {
if (t) {
t = new elem;
t->key = n;
t->left = t->right = NULL;
}
else {
if (t->key < n)
add(n, t->right);
else
add(n, t->left);
}
}
Your condition for adding the node is incorrect. It should be if (!t). The location of a new node in a binary search tree must be as the child of a node with at least one null child pointer. To add the node, you need the recursion to get to one of these null pointers and then add the node there.
Think about what happens when you pass the initially-null root to the add function. The condition in the first if statement is false, so when you try to check the condition if (t->key < n), you are attempting to access the key field of a non-existent object.
Related
I'm trying to learn some basics about single linked lists, so I went with idea of creating some code. Sadly, I have given constructor to follow.
Untill now I've created all methods I've wanted. Unfortunately, seems like my insert doesn't work, so I can't even check if other methods works. Ofc role of insert method is to add number into sorted list L. This number should be put before first number, if it's bigger or put at the end of the list, if there is no such number.
#include <iostream>
#include <cassert>
using namespace std;
struct lnode
{
int key;
lnode* next;
lnode(int k, lnode* n=nullptr):key(k),next(n){}
};
void insert( lnode* &L, int x)
{
while(L)
{
if(x >= L->key)
{
L = L->next;
}
else
{
lnode* temp = L;
L = new lnode(x, nullptr);
L->next = temp;
break;
}
}
}
int main()
{
lnode* t = nullptr;
insert(t,3);
insert(t,4);
insert(t,1);
insert(t,7);
insert(t,-4);
insert(t,9);
insert(t,2);
while(L) {
std::cout << L->key << " ";
}
}
What do I expect? My expectations is to see elements of my list. At this moment there is nothing. No error, no result.
The trick to writing simple singly-linked list modifying code is to use a pointer to the pointer current node to indicate your position:
void insert( lnode* &L, int x)
{
lnode **pos = &L;
while (*pos && (*pos)->key <= x) {
pos = &((*pos)->next);
}
*pos = new lnode(x,*pos);
}
Since you are, as you say, a beginner, maybe you should start with the beginner version:
void insert( lnode* &L, int x)
{
if (!L || L->key > x) {
//insert at head
L = new lnode(x, L);
return;
}
lnode *previous=L;
lnode *current=L->next;
while(current && current->key <= x) {
previous = current;
current = current->next;
}
//insert between previous and current
previous->next = new lnode(x, current);
}
Comparing to the previous one shows the benefit of using lnode ** to track the insert position as you search:
no special case for inserting at the head
no separate variables for previous and next
This code should work. Fixed the compilation error and also the traversing logic while printing on top of Matt's code.
#include <iostream>
#include <cassert>
using namespace std;
struct lnode
{
int key;
lnode* next;
lnode(int k, lnode* n = nullptr) :key(k), next(n) {}
};
void insert(lnode* &L, int x)
{
lnode **pos = &L;
while (*pos && (*pos)->key <= x) {
pos = &((*pos)->next);
}
*pos = new lnode(x, *pos);
}
int main()
{
lnode * t = nullptr;
insert(t, 3);
insert(t, 4);
insert(t, 1);
insert(t, 7);
insert(t, -4);
insert(t, 9);
insert(t, 2);
while (t) {
std::cout << t->key << " ";
t = t->next;
}
}
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;
}
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.
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!
I was wondering how I would add a counter that represents the number of comparisons in my BST. I added a counter but my printTree function for some reason I keep getting 0 for the count. Am I suppose to count the number of comparisons made in the print function? Or should I have a separate function specifically for counting the number of comparisons made?
#include <iostream>
#include <cstdlib>
#include <fstream>
using namespace std;
struct node
{
int data;
node* left;
node* right;
};
node* root = NULL;
node* createLeaf(int data)
{
node* n = new node;
n->data = data;
n->left = NULL;
n->right = NULL;
return n;
}
void addLeaf(node* &curr, int data)
{
//If curr = NULL then add node
if(curr == NULL)
{
curr = createLeaf(data);
}
//Left(Less than)
else if(data <= curr->data)
{
addLeaf (curr->left, data);
}
//Right(greater than)
else if(data >= curr->data)
{
addLeaf(curr->right, data);
}
}
int printTree(node* Ptr, ofstream& NewData, int count)
{
//Check if tree is empty
if(root != NULL)
{
return count++;
if(Ptr->left != NULL)
{
printTree(Ptr->left, NewData, count);
}
NewData << Ptr->data; //Store Data in output file
NewData << endl;
cout << Ptr->data << " ";
if(Ptr->right != NULL)
{
printTree(Ptr->right, NewData, count);
}
}
else
{
cout << "The Tree is empty\n";
}
return Ptr->data;
}
int main()
{
ifstream dataFile;
dataFile.open("Data.txt.");
int temp, count;
count = 0;
while(dataFile)
{
dataFile >> temp;
addLeaf(root, temp);
}
dataFile.close();
ofstream NewData;
NewData.open("NewData.txt");
count = printTree(root, NewData, count);
cout << "count:" << count;
NewData.close();
system("PAUSE");
return 0;
}
Simply pass the count variable by reference (Or use a pointer. Example uses pass by reference) and then increment without returning and this will give you a simple way of counting the number of comparisons. Edited snippets of your code are below.
Note: For future reference post incrementing value to be returned will do nothing if it is being returned. e.g. use return ++count; instead of return count++;. This is why you where getting zero as the value of your count variable. A simple way of explaining this behavior is that when you return a post-incremented value it returns the value and exists that function before incrementing it. Although from what I understand of the code you did not really want to be returning the count variable.
int printTree(node* Ptr, ofstream& NewData, int &count)
{ // ^ The & specifies that is to be passed
// by reference.
//Check if tree is empty
if(root != NULL)
{
// No longer returns instead just increments.
count++;
// Your code here.
}
// Your code here.
}
int main()
{
int count = 0;
// The rest of your code here ....
// Stores the return value from print tree root "ptr->data"
int data = 0;
// New caller will modify count as it is passed by reference, but will "return ptr->data;"
data = printTree(root, NewData, count);
cout << "count:" << count;
system("PAUSE");
return 0;
}
I'd do it by defining a tiny class that was devoted primarily to counting comparisons:
template <class T>
struct holder {
static int count;
T t;
holder(T T) : t(t) {}
operator T() const { return t; }
operator <(T const &r) { ++count; return t < r.t; }
};
int holder::count = 0;
Then a node would hold instances of these instead of holding ints directly:
struct node {
holder<int> data;
node *left;
node *right;
};
Do your work with your tree, and when you want to know the number of comparisons you've done so far, look at holder<int>::count; to get it.