In header file I have:
typedef struct bst_node {
char key; // kľúč
int value; // hodnota
struct bst_node *left; // ľavý potomok
struct bst_node *right; // pravý potomok
} bst_node_t;
And in my c file I want to insert a binary tree using a double pointer:
void bst_insert(bst_node_t **tree, char key, int value) {
if(*tree == NULL){
*tree = malloc(sizeof(struct bst_node));
(*tree)->key = key;
(*tree)->value = value;
(*tree)->right = NULL;
(*tree)->left =NULL;
}
else if(key == (*tree)->key){
(*tree)->value = value;
}
else if((*tree)->key > key){
bst_insert(&(*tree)->left, key, value);
}else{
bst_insert(&(*tree)->right, key, value);
}
}
But when I try to run tests I get this munmap_chunk(): invalid pointer
Aborted
How can I fix this? Is problem somewhere with the pointer?
Related
I'm new to C programming and this is my first time working on a complicated program. The program will put a phonebook (name and number) in a binary search tree. The question that arises is why I get an error with the Recursion and all pointers that I used in the program.
My struct def is also probably wrong..
Would be happy if anyone could point me to the problem and how to solve it.
typedef struct _bstree {
char * name[60];
unsigned long phone;
struct bstree *left;
struct bstree *right;
}bstree;
typedef struct _bst_node {
int value;
struct node* next;
}bst_node;
and here are the functions (I'm not allowed to change the type of the functions or their arguments):
void bst_insert_node(bstree* bst, unsigned long phone, char *name) {
if (bst == NULL) {
bstree *newNode = (bstree *)malloc(sizeof(bstree));
newNode->phone = phone;
strcpy(newNode->name,name);
newNode->left = NULL;
newNode->right = NULL;
}
else if (bst->phone>phone) {
bst_insert_node(bst->left,phone, name); //ERROR
}
else {
bst_insert_node(bst->right, phone, name); //ERROR
}
}
bst_node* find_node(bstree* bst, unsigned long phone) {
if (bst==NULL) {
printf("Cannot find Number");
return NULL;
}
//if phone ist root
if (phone== bst->phone)
return bst; //ERROR
bstree* searching = NULL;
//left search
searching = find_node(bst->left,phone); //ERROR
if (searching)
return searching; //ERROR
// right search
searching = find_node(bst->right,phone); //ERROR
if (searching)
return searching; //ERROR
if (searching)
return searching; //ERROR
return NULL;
}
typedef struct _bstree {
char * name[60];
unsigned long phone;
struct bstree *left;
struct bstree *right;
}bstree;
Why does your tree structure have left and right.The nodes of the tree should have left and right and not the tree itself.The tree structure should just have a root node.
typedef struct _bst_node {
char name[60];
unsigned long phone;
struct _bst_node *left;
struct _bst_node *right;
}bst_node;
and then the tree structure
typedef struct _bstree {
bst_node *root; //this will point to the root node of the tree and will be NULL if the tree is emty.
}bstree;
Your insert() function should take bstree as input and insert a new bst_node in the tree.Remeber your root is bsttree::root and not bsttree itself.
void bst_insert_node(bstree* bst, unsigned long phone, char *name)
{
//insert new node
}
try this code buddy
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct _bst_node
{
char name[60];
unsigned long phone;
} bst_node;
typedef struct _bstree
{
bst_node key;
struct _bstree * left;
struct _bstree * right;
} bstree;
static inline bstree * create_node(unsigned long phone, char * name)
{
bstree * newNode = (bstree *) malloc(sizeof(bstree));
newNode->key.phone = phone;
strcpy(newNode->key.name, name);
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
void bst_insert_node(bstree * bst, unsigned long phone, char * name)
{
if (bst == NULL)
{
return;
}
if (bst->key.phone > phone)
{
if (bst->left == NULL)
{
bst->left = create_node(phone, name);
return;
}
bst_insert_node(bst->left, phone, name);
}
else
{
if (bst->right == NULL)
{
bst->right = create_node(phone, name);
return;
}
bst_insert_node(bst->right, phone, name);
}
}
bst_node * find_node(bstree* bst, unsigned long phone)
{
if (bst == NULL)
{
return NULL;
}
if(bst->key.phone > phone)
{
return find_node(bst->left, phone);
}
else if (bst->key.phone < phone)
{
return find_node(bst->right, phone);
}
return &(bst->key);
}
void print_tree(bstree * bst, int level)
{
int temp = 0;
while(temp < level)
{
printf("-");
++temp;
}
printf(" (%ld-%s)\n", bst->key.phone, bst->key.name);
if (bst->left != NULL)
{
print_tree(bst->left, level + 1);
}
if (bst->right != NULL)
{
print_tree(bst->right, level + 1);
}
}
I've got a structure type like the following:
typedef struct TreeNode{
int val;
struct TreeNode *left;
struct TreeNode *right;
} TreeNode;
To add an element to my
TreeNode* insert(TreeNode *root, int val){
TreeNode* a;
a = root;
int i;
if(a==NULL){
a -> val = val;
a -> left = NULL;
a -> right = NULL;
}
else if(a->val < val){
return insert(root->left,val);
}
else if(a->val > val)
return insert(root->right,val);
}
This gives no output when i evaluate it. What is my fault?
In the a == NULL case, you need to allocate memory for the node. Otherwise a -> val is illegal.
Also need to add a return to the code. You can return (a). Then when you call the function, you call it as root = insert(root, val)
The code is below.
TreeNode* insert(TreeNode *root, int val){
TreeNode* a;
a = root;
int i;
if(a==NULL){
// Allocate memory here
a = malloc(sizeof (root));
if (a== NULL)
{
// Malloc error, You can exit the program or print a debug message here
}
a -> val = val;
a -> left = NULL;
a -> right = NULL;
}
else if(a->val < val){
return insert(root->left,val);
}
else if(a->val > val)
return insert(root->right,val);
return a;
}
I am trying to make a BST from a given array and then traverse it In-Order. There are no compilation errors but at run time the error is Segmentation fault (core dumped). I have been unable to figure out the cause of the error(tried to browse stackoverflow for similar cases). The code is as follows:
#include<stdio.h>
#include<stdlib.h>
struct TreeNode{
int data;
struct TreeNode *right;
struct TreeNode *left;
};
struct TreeNode *newTreeNode(){
struct TreeNode *node = malloc(sizeof(struct TreeNode));
if(node){
node->data = 0;
node->left = NULL;
node->right = NULL;
return node;
}
else{
printf("Memory Error");
}
};
void InorderTraversalRecursive(struct TreeNode *node){
InorderTraversalRecursive(node->left);
printf("%d",node->data);
InorderTraversalRecursive(node->right);
}
struct TreeNode *InsertIntoTree(struct TreeNode *node, int data){
if(node == NULL){
node = newTreeNode();
node->data = data;
node->left = node->right = NULL;
}
else{
if(data > node->data)
InsertIntoTree(node->right, data);
else if(data < node->data)
InsertIntoTree(node->left, data);
}
return node;
}
struct TreeNode *MakeTreeFromData(int *arr){
int size = sizeof(arr)/sizeof(arr[0]);
struct TreeNode *root;
root = newTreeNode();
int i;
for(i=0;i<size;i++){
InsertIntoTree(root,arr[i]);
}
return root;
}
void main(){
int data[] = {4,2,6,1,7,3,5,8};
struct TreeNode *root;
root = MakeTreeFromData(data);
InorderTraversalRecursive(root);
}
One more error is in function InorderTraversalRecursive. The code should be:
void InorderTraversalRecursive(struct TreeNode *node)
{
if(!node)
return;
InorderTraversalRecursive(node->left);
printf("%d",node->data);
InorderTraversalRecursive(node->right);
}
This would eliminate the segmentation fault.
You should pass the size of array in function MakeTreeFromData().
So the declaration becomes
struct TreeNode *MakeTreeFromData(int *arr,int size)
where size is calculated by the same formula but inside main and then passed to the function.
Moreover, the function InsertIntoTree() should be defined as
struct TreeNode *InsertIntoTree(struct TreeNode *node, int data)
{
if(node==NULL)
{
node = newTreeNode();
node->data = data;
node->left = node->right = NULL;
}
else
{
if(data >= node->data)
node->right = InsertIntoTree(node->right, data);
else
node->left = InsertIntoTree(node->left, data);
}
return node;
}
And voila you get the correct output!!!
One obvious error is in this line
int size = sizeof(arr)/sizeof(arr[0]);
where arr is not an array but a pointer. This doesn't do at all what you think it is doing. You'd have to pass the size of your array as a parameter to your function.
If you have one powerful tool to know about when coding in C is GDB.
Read some tutorials and you won't need to ask this questions.
In my personal experience, I loved the gdb experience with emacs.
i am writing a Dictionary using linked list in C, and all my functions work except my delete function, which is shown below along with all other necessary code. Every time i try to run my program as soon as it reaches a line in which it must delete a node, it gives me the error: Segmentation Fault (core dumped) which means it has something to do with the memory allocation or a null pointer i think. I know that the rest of my code works. All and any help is appreciated! :)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#include"Dictionary.h"
// NodeObj
typedef struct NodeObj{
char* key;
char* value;
struct NodeObj* next;
} NodeObj;
// Node
typedef NodeObj* Node;
// newNode()
// constructor of the Node type
Node newNode(char* key, char* value)
{
Node N = malloc(sizeof(NodeObj));
assert(N!=NULL);
// if(key!=NULL && value!=NULL){
N->key = key;
N->value = value;
N->next = NULL;
// }
return(N);
}
// DictionaryObj
typedef struct DictionaryObj{
Node head;
int numItems;
} DictionaryObj;
// newDictionary()
// constructor for the Dictionary type
Dictionary newDictionary(void){
Dictionary D = malloc(sizeof(DictionaryObj));
assert(D!=NULL);
D->head = NULL;
D->numItems = 0;
return D;
}
Node findKey(Dictionary D, char*key){
Node N;
N = D->head;
while(N != NULL){
if(strcmp(N->key,key)==0){
return N;
}
N = N->next;
}
return NULL;
}
char* lookup(Dictionary D, char* k){
if(findKey(D, k)==NULL){
return NULL;
}else{
Node N;
N = findKey(D, k);
return N->value;
}
}
void delete(Dictionary D, char* k)
{
if(lookup(D,k) == NULL){
fprintf(stderr,
"KeyNotFoundException: Cannot delete non-existent key\n");
exit(EXIT_FAILURE);
}
int check = strcmp(D->head->key, k);
if(check == 1){
D->head = D->head->next;
return;
}
Node cur;
Node prev;
cur = D->head;
prev = NULL;
while( cur != NULL){
int ret1;
ret1 = strcmp(cur->key, k);
while( ret1 == 0){
prev = cur;
cur = cur->next;
}
}
prev->next = cur->next;
D->numItems--;
}
The NodeObject should store copy of the string and care for deleting it:
typedef struct Node Node;
struct Node {
Node *next;
char *key, *value;
};
Node* newNode(char* key, char* value) {
assert(key && value);
Node* node = (Node*)malloc(sizeof(Node));
assert(node);
node->next = NULL;
node->key = strdup(key);
node->value = strdup(value);
}
void delNode(Node* node) {
free(node->key);
free(node->value);
}
Consider using the original code (without that strdup) in this scenairo:
Node* prepare() {
char key_buf[20]; strcpy(key_buf, "mykey");
char val_buf[20]; strcpy(val_buf, "myval");
return newNode(key_buf, val_buf);
}
void examine(Node* node) {
printf("Node key=%s value=%s\n", node->key, node->value);
}
int main() {
examine(prepare());
}
the above code would crash because Node would have pointers to stack (in your case without that strdup), but key_buf+val_buf were only valid inside prepare() (garbage outside and therefore inside examine() - node->key points to random data).
I get a dereferencing pointer to incomplete type on line 58: rootNode->_left = NULL. Any ideas?
Also there is a lot of code commented out to single out this error but I have another question about the format of this ADT:
The usual Binary Search Tree structures out there that just have a Node class and all the BST functions such as insert take and return a node. Here however I have to use a separate Tree structure that has a root which is another structure TNode. This has been problematic for me for example in the addStringToTree function it only returns and takes a Tree parameter. So I don't know how to recurse on that in the usual way with Nodes. I created a helper function as my solution but not sure this is ideal.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <stdbool.h>
typedef struct TNode {
struct TNode* _left;
struct TNode* _right;
struct TNode* _key;
} TNode;
typedef struct Tree {
TNode* _root;
} Tree;
Tree* makeEmptyTree();
void destroyTree(Tree* root);
Tree* addStringToTree(Tree* t, char* value);
TNode* addStringToTreeHelper(TNode* node, char* value);
bool lookupInTree(Tree* t, char* value);
void traverse(TNode* root);
struct Tree* wordTree;
struct TNode* wordRoot;
int main() {
if(wordTree = makeEmptyTree()) {
printf("Tree initialized.\n");
/// traverse(wordTree->_root);
addStringToTree(wordTree, "peter");
//printf(wordTree->_root->_key);
//traverse(wordTree->_root);
} else {
printf("Error initializing tree.\n");
}
return 0;
}
Tree* makeEmptyTree() {
struct Tree* theTree = malloc(sizeof(struct Tree*)); // allocate memory for Tree
theTree->_root = NULL;
return theTree;
}
Tree* addStringToTree(Tree* t, char* value) {
if(t->_root == NULL) {
struct Tnode* rootNode = malloc(sizeof(struct TNode*));
rootNode->_left = NULL;
//rootNode = (TNode*)malloc(sizeof(struct TNode));
//strcpy(rootNode->_key, value);
// rootNode->_left = NULL;
// rootNode->_right = NULL;
//printf(rootNode->_key);
} else {
//addStringToTreeHelper(root, value);
}
return t;
}
TNode* addStringToTreeHelper(TNode* node, char* value) {
// node = malloc(sizeof(TNode)); // What is going on
if(strcmp(value, node->_key) < 0) {
node->_left = addStringToTreeHelper(node->_left, value);
} else if(strcmp(value, node->_key) > 0) {
node->_right = addStringToTreeHelper(node->_right, value);
}
return node;
}
void traverse(TNode* root) {
// if(root != NULL) {
// traverse(root->_left);
// printf("%s\n", root->_key);
// traverse(root->_right);
// } else {
// printf("Empty Tree\n");
// }
}
2nd Edit
Wow just a silly typo. Thanks guys. Also the _key variable of TNode should be of type char* instead of struct TNode* rolls eyes
struct Tnode* rootNode = malloc(sizeof(struct TNode*));
Should be
struct Tnode* rootNode = malloc(sizeof(struct TNode));
You're only allocating enough memory for a pointer and then pointing to it.
EDIT:
That should be TNode* rootNode not Tnode* rootNode.