why such an annoying binary search tree(bst) seg.fault error? - search

input no. of elements , elements of binary search tree , input elemt whoose subtree you want to display
#include <stdio.h>
defn of struct node of bst
typedef struct node
{
int info;
struct node *right, *left;
}NODE;
insert fn , node at leaf
struct node* insertBst(struct node* root, int ele)
{
if(root == NULL)
{
NODE* temp = (NODE*)malloc(sizeof(NODE));
temp -> info = ele;
temp -> right = temp -> left = NULL;
return root;
}
else if(ele > root -> info)
{
root -> right = insertBst(root -> right, ele);
}
else if(ele < root -> info)
{
root -> left = insertBst(root -> left, ele);
}
}
searching for the address of the ele
NODE* search(int ele, NODE* root)
{
if( root == NULL) return NULL;
if(ele > root -> info)
{
return search(ele, root -> right);
}
else if( ele < root -> info)
{
return search(ele, root -> left);
}
else if(ele == root -> info) //ele found
{
return root;
}
}
displaying the made bst
using pre order : ROOT , LEFT, RIGHT
void preorder(NODE* root)
{
if(root)
{
printf("%d ", root -> info);
preorder(root -> left);
preorder(root -> right);
}
}
driver where i call insert to create my bst, node whose subtree im >>displaying
int main()
{
int n, ele; //no. of elements in bst
NODE* root = NULL;
printf("no. of bst elements");
scanf("%d", &n);
printf("elements to be inserted in bst");
for(int i = 0; i < n; ++i)
{
scanf("%d", &ele);
NODE* t = insertBst(root, ele);
}
printf("element whose subtree needs to be displayed");
scanf("%d", ele); //elements whose subtree is to be diplayed
NODE *temp;
temp = search(ele, root);
preorder(temp);
}

Probably the segfault is in the line:
scanf("%d", ele);
Where you should have passed the address of ele instead of it's value, like you did inside the for loop.
Also, your program won't work because function insertBst will never assign a root node as any time if(root == NULL) is true (always) you will allocate a node as you should, but you returns the same root which is still NULL. You probably meant to return temp.
Also, it's good practice to check temp (after the malloc) for NULL pointer before dereferencing it, as malloc can fail and return NULL, and dereferencing it will crash your program.

Related

Check50 Errros: Not passing " handles most basic words properly" and "handles substrings properly" tests. Check50 also can't check for a memory error

I am working on Pset5 Speller. I've managed to get all my errors down to three, but I cannot figure out how to fix my program so that it handles most basic words and handles substrings. I have run debugger, but it doesn't really help. I have also run valgrind and it says that no memory leaks are possible. I think the problem maybe my check function or hash function, so I have changed them a few times but I still get the same check50 results. The sumbit50 link:
https://submit.cs50.io/check50/57b8af186bcdadea0b585f0785ef47a5cf317b99 says that check50 only ever finds 1 word in the dictionary and identifies all words as misspelled. I really am not quite sure what the problem is. Can someone help me please? Here are my checks and hash functions. Thank you!!!
// Hashes word to a number
unsigned int hash(const char *word)
{
// hash function created by Deliberate Think on Youtube
int hash_key = 0;
int n;
for (int i = 0; word[i] != '\0'; i++)
{
if (isalpha(word[i]))
{
n = word[i] - 'a' + 1;
}
else
{
n = 27;
}
hash_key = ((hash_key << 3) + n) % N;
}
return hash_key;
}
// Returns true if word is in dictionary else false
bool check(const char *word)
{
// create an array to store words, then copy words from table to compare
int n = strlen(word);
char wordcheck[LENGTH + 1];
strcpy(wordcheck, word);
for (int i = 0; i < n; i++)
{
wordcheck[i] = tolower(word[i]);
}
//hashes word, then accesses linked list at that value
int j = hash(wordcheck);
node *cursor = hashtable[j];
if (hashtable[j] != NULL)
{
//iterates through linked list: cursor pointer starts at head of list and while there is a value, it moves on to the next word in the list
while (cursor != NULL)
{
//if the word is found, return true
if (strcmp(cursor->word, wordcheck) == 0)
{
return true;
}
else
{
cursor = cursor->next;
}
}
}
return false;
}
bool load(const char *dictionary)
{
//opens dictionary file
FILE *inputfile = fopen(dictionary, "r");
if (inputfile == NULL)
{
return false;
}
//initializes new node pointer and reads words from new file while !EOF
char word[LENGTH + 1];
while (fscanf(inputfile, "%s", word) != EOF)
{
//actually creates and initializes new node( creates space in memory for node using malloc function) and copies word into node while keeping tracking of # of words
node *new_node = malloc(sizeof(node));
if (new_node == NULL)
{
unload();
return false;
}
else
{
strcpy(new_node->word, word);
}
//hashes words in node to determine which linked list to use
int j = hash(new_node->word);
//initializes node pointer to first bucket in hashtable
node *head = hashtable[j];
if (head == NULL)
{
//if there is no data in linked list, new_node becomes head of linked list
hashtable[j] = new_node;
}
else
{
//if data exists, node points to next word in list, then head of linked list points to node pointer
new_node->next = hashtable[j];
hashtable[j] = new_node;
}
wordcount++;
fclose(inputfile);
}
return true;
}
I solved it! I had to change the way the hash function was written inside of the load function and rewrite fclose(inputfile) to be outside of one of the curly braces. All errors gone!

CS50 pset5 Speller

That is my first post here, and I need help.
Speller's output for lalaland.txt is 958 words, but should be 955. (3 x "i'd").
I have tried to hard-code "i'd", but then output was ~850. (program declined all of "i'd").
tolstoy.txt - 13117, but must be 13008, most words are two-letters (Ha, ha, ga, Ma, I'd, etc.).
Same time other part of same word passing check.
Same situation with all other texts. Program passing and declining same words with no reason.
I have no idea what is happening.
Here is my load();
bool load(const char *dictionary)
{
FILE *inputFile = fopen(dictionary, "r");
if (inputFile == NULL)
{
return false;
}
while (true)
{
node *n = malloc(sizeof(node));
if (n == NULL)
{
return 1;
}
n->next = NULL;
int sc = fscanf(inputFile, "%s", n->word);
if (sc == EOF)
{
free(n);
break;
}
int bucket = hash(n->word);
if (table[bucket] == NULL)
{
table[bucket] = n;
}
else
{
n->next = table[bucket]->next;
table[bucket]->next = n;
}
sizeCount++;
}
fclose(inputFile);
return true;
}
And check();
bool check(const char *word)
{
int i = hash(word);
if (table[i] == NULL)
{
return false;
}
struct node *checker = malloc(sizeof(node));
checker = table[i];
while (true)
{
if (strcasecmp(checker->word, word) == 0)
{
return true;
}
if (checker->next == NULL)
{
break;
}
checker = checker->next;
}
free(checker);
return false;
}
Remember, table is an array of node pointers, not an array of nodes. Therefore, there is no memory allocated for a next or word element. These lines in load are accessing memory that does not belong to table[bucket]:
n->next = table[bucket]->next;
table[bucket]->next = n;
Since table is the head of the list, there is no need to allocate a node in check. If checker is a node pointer, initialized to table[bucket], the program will crawl the list just fine, and (should) only access allocated memory.
The memory violations are causing the unpredictable results. You could run valgrind -v to see the full report.

how to find the horizontal distance between two nodes at the same level in a binary tree?

Given a binary tree:
Binary tree of height 3
I want to find the horizontal distance between two nodes at the same level also counting the nodes that are not there in between while not counting the nodes themselves,
Say in
f
/ \
g h
/ \ / \
a d
in between the nodes a and d there is a horizontal distance of 2.
Edit:
Please see distance between a to d is calculated on the same level not including the parent or child nodes of either a or d but only the missing nodes at the same level. so distance between a to d would be a>(x>y)>d where in x and y are the missing child nodes of node g and h respectively. Hence not counting the target nodes a and d there'll be a horizontal distance of 2
Think of it this way:
a
/ \
b c
/ \ / \
e f g h
Now, you want to determine horizontal distance between nodes at the same level. Eg: f and g.
Here is a step by step approach:
Perform a level order traversal of the binary tree and store the values in an array.
This results in an array with its elements as node values.
Traverse the array elements. When you encounter f (starting node), set counter to 0.
Keep traversing the array and check that:
If the g (end node) is encountered, then stop traversing.
If the counter has been set, and the end node is not encountered, then update the value of the counter by 1.
Finally, print the value of the counter.
Update:
As pointed out by anand_v.singh, if the tree might not be completely filled at all levels, then it can produce wrong results.
To overcome this problem, an additional parameter called tree_height will be determined. Suppose, the height of the tree was 3, then the array will contain at most 2tree_height -1 elements, all initialized to a value that is not equal to the value of any tree nodes.
Now, you can use something like array representation of binary heap, to place node values into the array, at their respective indices. Then follow the above-mentioned procedure to obtain the results.
This is one approach that might not be the best and optimal solution in terms of memory.
So suggestions/ improvements are welcome.
Algorithm-
Traverse BT using a Breadth-First Search (Level order) approach.
While traversing, consider blank spaces(where node isn’t present) as ‘-1’
Insert BFS path elements in an array Find indices of 2 node elements to be found.
Calculate distance using indexes.
Complexity-
Time: O(N)
Space: O(N)
Assumptions-
Every node in BT has a unique value.
class Node {
Node() {
value = -1;
}
Node(int num) {
value = num;
}
int value;
Node left = null;
Node right = null;
}
Declaring some required DS
static Queue<Node> queue = new LinkedList<Node>();
static ArrayList<Integer> list = new ArrayList<Integer>();
static Set<Integer> set = new HashSet<Integer>();
Then three functions
static void convertBTToArray() {
if (set.isEmpty())
return;
Node node = queue.poll();
if (node != null) {
list.add(node.value);
if (node.value != -1)
set.remove(node.value);
if (node.left != null) {
queue.add(node.left);
set.add(node.left.value);
} else
queue.add(new Node());
if (node.right != null) {
queue.add(node.right);
set.add(node.right.value);
} else
queue.add(new Node());
convertBTToArray();
} else
return;
}
static void init(Node root) {
// traverse in BFS fashion (level order) and convert to Array.
Node rootCopy = root;
if (rootCopy != null) {
queue.add(rootCopy);
set.add(rootCopy.value);
convertBTToArray();
}
}
// get distance between start and end values.
static int getHorizontalDistance(int startValue, int endValue) {
int startIndex = -1, endIndex = -1;
for (int i = 0; i < list.size(); i++) {
if (startIndex == -1)
startIndex = list.get(i) == startValue ? i : -1;
if (list.get(i) == endValue) {
endIndex = i;
break;
}
}
// check if both numbers are from same level else return -1
if (Math.floor(Math.log(startIndex + 1) / Math.log(2)) >= 0
&& Math.floor(Math.log(endIndex + 1) / Math.log(2)) >= 0)
return (endIndex - startIndex - 1);
else
return -1;
}
and finally the main method
public static void main(String...s) {
// create your tree and enter elements here
// -1 indicates that distance cant be found and hence invalid input.
System.out.println("Dist(7,1): "+getHorizontalDistance(7, 1));
}
Find horizontal distance(hd1) of 'a' from 'f' i.e root and horizontal distance(hd2) of 'd' from 'f'.
Take hd of root=0.
Then do hd2-hd1 to get the horizontal distance b/w given two nodes. Here hd1 would be negative since it's to the left of the root and hd2 would be positive since it's to the right of the root.
Function to calculate horizontal distance of a node would look like this.
int HD(Node* root, Node* node, int hd=0){
if(!root) return INT_MIN;
if(root==node) return hd;
return max(HD(root->left, node, hd-1), HD(root->right, node, hd+1));
}
Now
hd1 = HD(root, nodeA)
hd2 = HD(root, nodeD)
hd2-hd1 will give 4 in your case.
Here is the code:
/**
*
* #author satish hawalppagol
*
*/
public class BinaryTreeTest
{
public int findDistance(Node root, int n1, int n2)
{
int leftNodeToRootNode = Pathlength(root, n1, "leftNodeToRootNode") - 2;
int rightNodeToRootNode = Pathlength(root, n2,"rightNodeToRootNode") - 2;
int lcaData = findLCA(root, n1, n2).data; //LCA->Lowest Common Ancestor
int lcaDistance = Pathlength(root, lcaData,"lcaDistance") - 1;
return (leftNodeToRootNode + rightNodeToRootNode) - 2 * lcaDistance;
}
public int Pathlength(Node root, int n1,String callingFrom)
{
if (root != null)
{
int x = 0;
if("rightNodeToRootNode" == callingFrom)
{
if(root.left ==null && root.right ==null)
{
//do nothing
}
else if(root.left ==null || root.right ==null)
{
System.out.println("counting the position where the node is not
present is : " + root.data);
}
if ((root.data == n1) || (x = Pathlength(root.left,
n1,"rightNodeToRootNode")) > 0 || (x = Pathlength(root.right,
n1,"rightNodeToRootNode")) > 0)
{
return x + 1;
}
}
if("rightNodeToRootNode" != callingFrom )
{
if ((root.data == n1) || (x = Pathlength(root.left,
n1,"leftNodeToRootNode")) > 0 || (x = Pathlength(root.right,
n1,"leftNodeToRootNode")) > 0)
{
return x + 1;
}
}
return 0;
}
return 0;
}
public Node findLCA(Node root, int n1, int n2)
{
if (root != null)
{
if (root.data == n1 || root.data == n2)
{
return root;
}
Node left = findLCA(root.left, n1, n2);
Node right = findLCA(root.right, n1, n2);
if (left != null && right != null)
{
return root;
}
if (left != null)
{
return left;
}
if (right != null)
{
return right;
}
}
return null;
}
public static void main(String[] args) throws java.lang.Exception
{
Node root = new Node(5);
root.left = new Node(2);
root.right = new Node(3);
/*root.left.right = new Node(12);*/
root.left.left = new Node(7);
root.left.left.left = new Node(9);
/*root.left.left.right = new Node(17);*/
root.right.right = new Node(1);
/*root.right.right.left = new Node(4);*/
root.right.right.right = new Node(6);
BinaryTreeTest binaryTreeTest = new BinaryTreeTest();
System.out.println("Distance between 9 and 6 is : " +
binaryTreeTest.findDistance(root,9, 6));
}
}
class Node
{
int data;
Node left;
Node right;
public Node(int data)
{
this.data = data;
this.left = null;
this.right = null;
}
}
///////////input/////////
// 5 //
// / \ //
// 2 3 //
// / \ \ //
// 7 1 //
// / \ / \ //
// 9 6 //
///////////input/////////
counting the position where the node is not present is : 2
counting the position where the node is not present is : 7
counting the position where the node is not present is : 3
counting the position where the node is not present is : 1
Distance between 9 and 6 is : 4

Binary Tree in C++/CLI with value is System::String

I have a problem when i try to insert node to binary tree. I don't understand why the argument is always null. Here is my program.
file "BinaryTree.h"
#pragma once
#ifndef BINARYTREE_H
#define BINARYTREE_H
using namespace System;
ref class BinaryTree
{
public:
BinaryTree()
{
root = nullptr;
};
~BinaryTree()
{
destroySubtree(root);
};
void insertNode(String^);
bool searchNode(String^);
void remove(String^);
String^ disPlay()
{
return disPlay(root);
};
private:
ref struct TreeNode
{
String^ values;
TreeNode ^left;
TreeNode ^right;
};
TreeNode ^root;
void insert(TreeNode ^, TreeNode ^);
void deleteNode(String^, TreeNode ^);
void destroySubtree(TreeNode ^);
void makeDeletion(TreeNode ^);
String^ disPlay(TreeNode ^);
};
#endif
And here is file "BinaryTree.cpp"
#include "BinaryTree.h"
using namespace System;
void BinaryTree::insert(TreeNode ^node, TreeNode ^newNode)
{
if (node == nullptr)
node = newNode;
else if (newNode->values->CompareTo(node->values)<0)
insert(node->left, newNode);
else
insert(node->right, newNode);
}
void BinaryTree::insertNode(String^ s)
{
TreeNode ^newNode = gcnew TreeNode;
newNode->values->Copy(s);
newNode->left = newNode->right = nullptr;
insert(root, newNode);
}
bool BinaryTree::searchNode(String^ s)
{
TreeNode ^node = root;
while (node)
{
if (node->values->CompareTo(s)==0)
return true;
else if (node->values->CompareTo(s) > 0)
node = node->left;
else
node = node->right;
}
return false;
}
void BinaryTree::remove(String^ s)
{
deleteNode(s, root);
}
void BinaryTree::deleteNode(String^ s,TreeNode ^node)
{
if (node->values->CompareTo(s) > 0)
deleteNode(s, node->left);
else if (node->values->CompareTo(s) < 0)
deleteNode(s, node->right);
else
makeDeletion(node);
}
void BinaryTree::makeDeletion(TreeNode ^node)
{
TreeNode ^tempNode;
if (node == nullptr){}
else if (node->right == nullptr)
{
tempNode = node;
node = node->left;
delete tempNode;
}
else if (node->left == nullptr)
{
tempNode = node;
node = node->right;
delete tempNode;
}
else
{
tempNode = node->right;
while (node->left)
{
tempNode = tempNode->left;
}
tempNode->left = node->left;
tempNode = node;
node = node->right;
delete tempNode;
}
}
void BinaryTree::destroySubtree(TreeNode ^node)
{
if (node)
{
if (node->left)
{
destroySubtree(node->left);
}
if (node->right)
{
destroySubtree(node->right);
}
delete node;
}
}
String^ BinaryTree::disPlay(TreeNode ^node)
{
String^ s;
if (node)
{
s = node->values;
return s+=disPlay(node->left);
return s+=disPlay(node->right);
}
return s;
}
When I use like this:
BinaryTree^ Tree = gcnew BinaryTree();
string key="abc0123456";
String^ sss = gcnew String(key.c_str());
Tree->insertNode(sss);
MessageBox::Show(Tree->disPlay());
but the result always null,when i check at step "Tree->insertNode(sss);" then the argument "sss" in function "insertNode(String^ s)", it mean variable "s" is null.
What should i do now to fix this problem?
Anyone can help me pls
Because String.Copy is static method, I believe. It returns back string which is not assigned to value field anywhere in you code
Something like
newNode->values = String::Copy(s);
might work
Your disPlay method will not recurse to right branches ever, Because it returns values + left recursion only.
I believe your intentios was something more like this:
String BinaryTree::disPlay(TreeNode ^node)
{
String s;
if (node)
{
s = node->values;
s+=disPlay(node->left);
s+=disPlay(node->right);
}
return s;
}

root always still null on my binary tree

import java.io.*;
class treeNode {
int data;
treeNode left = null;
treeNode right = null;
treeNode parent = null;
treeNode (int value)
{
data = value;
}
}
class treeNodes {
treeNode root = null;
void insert (treeNode node)
{
if (root == null) // the value of root is always null
{
root = node;
return;
}
treeNode cur = null;
treeNode father = null;
while (cur != null)
{
father = cur;
if (cur.data > node.data)
cur = cur.left;
else
cur = cur.right;
}
if (father.data > node.data)
father.left = node;
else
father.right = node;
node.parent = father;
}
void walkInorder (treeNode n)
{
if (n == null)
return;
walkInorder (n.left);
System.out.print (n.data + " ");
walkInorder (n.right);
}
}
class binarySearchTree {
public static void main (String [] args) {
treeNodes obj1 = new treeNodes ( );
System.out.println ("============ Array Elements ============");
int A[] = {3, 5, 7, 9, 8, 6};
for (int i = 0; i < 6; i++)
{
treeNode node = new treeNode (A[i]);
treeNodes obj = new treeNodes ( );
obj.insert(node);
}
System.out.println ("\n============ Inorder ============");
System.out.println (obj1.root.data);
obj1.walkInorder (obj1.root);
}
}
i'm tried to make binary tree and when i send the first value to insert function it should change the value of root
In my case the root never change can someone tell me why and how can i solve it
sorry for my bad english
Inside your for loop, for each item in your array, you are creating a new treeNodes instance. Whenever you create a new instance, root is set to null.
Try making the following change to your for loop:
treeNodes obj = new treeNodes();
for (int i = 0; i < 6; i++)
{
treeNode node = new treeNode(A[i]);
obj.insert(node);
}
This way, every step of your loop will use the same treeNodes instance, and the root node will correctly be set. There are other problems with your code, but part of learning is experimenting. So, go ahead, fix the issue above and let us know how it goes.
I guess the answer above is not completely right. Yes, you'll be creating a new treeNodes instance everytime the loop goes to the next element in your array, but that would mean you were creating new trees with only one element, so the root would not be null.
The roots you are trying to print, in the other hand, are null in fact, but thats because you did not insert any element in the tree you are trying to print.
You tried to walk in order the tree OBJ1, and you didnt insert anything into this tree. You should try to walk in order the tree OBJ.
The answer above is right, you need to make that fix, so you will insert the array elements into only one tree, and then fix this issue i explained.

Resources