Binary Search tree, node deletion crash - c

I coded a Binary Search tree. Every function works just fine, but the "deletenode". This method is supposed to delete the node which *p is pointing at.
However if the node is a leaf it prints the tree without the node and crashes.
If the node is no leaf it doesnt even print the tree and crashes.
I dont see any possible way to recreate the problem in less code, because i dont know where the problem is supposed to be. I'm Sorry.
Maybe someone can load it up and see where the problem is, because im really desperate.
#include <stdio.h>
void *malloc(size_t size);
void free(void *ptr);
struct tnode {
int content;
struct tnode *left; /* left subtree */
struct tnode *right; /* right subtree */
};
struct tnode *talloc(void) /* reserves memory*/
{
return (struct tnode *) malloc(sizeof(struct tnode));
}
struct tnode *addelement(struct tnode *p, int i) /* addelement: adds new node */
{
int cond;
if(p == NULL) {
p = talloc(); /* make a new node */ p->content = i;
p->left = p->right = NULL;
} else if(p->content == i) {
return p;
} else if(i < p->content) /* goes to the left side */ p->left = addelement(p->left, i);
else /* goes to the right side */ p->right = addelement(p->right, i);
return p;
}
struct tnode *addtree(struct tnode *top, struct tnode *p) /* adds subtree to main tree*/
{
if(p == NULL)
return top;
else
return addtree(addtree(addelement(top, p->content), p->right), p->left);
}
int printtree_preorder(struct tnode *p) /* prints tree in preorder*/
{
if(p != NULL) {
printf("%d \n", p->content);
printtree_preorder(p->left);
printtree_preorder(p->right);
}
return 0;
}
int printtree_inorder(struct tnode *p) /* prints tree in inorder*/
{
if(p != NULL) {
printtree_inorder(p->left);
printf("%d \n", p->content);
printtree_inorder(p->right);
}
return 0;
}
int printtree_postorder(struct tnode *p) /* prints tree in postorder*/
{
if(p != NULL) {
printtree_postorder(p->left);
printtree_postorder(p->right);
printf("%d \n", p->content);
}
return 0;
}
struct tnode *searchnode(struct tnode *p, int nodtodelete) /* pointer is set on the node which is supposed to be deleted */
{
if(p == NULL) {
printf("Baum ist leer oder Element nicht vorhanden \n");
return 0;
}
if(p->content == nodtodelete) {
return p;
}
if(p->content < nodtodelete) {
return searchnode(p->right, nodtodelete);
}
if(p->content > nodtodelete) {
return searchnode(p->left, nodtodelete);
}
}
struct tnode *deletenode(struct tnode *p, struct tnode *pBaum) /* Is supposed to delete the node which the *p is pointing at */
{
if((p->left == NULL) && (p->right == NULL)) {
free(p);
printf("Ist Blatt \n");
return pBaum;
}
if((p->left == NULL) && (p->right != NULL)) {
struct tnode *rechterTeilbaum = p->right;
free(p);
pBaum = addtree(pBaum, rechterTeilbaum);
return pBaum;
}
if((p->right == NULL) && (p->left != NULL)) {
struct tnode *linkerTeilbaum = p->left;
free(p);
pBaum = addtree(pBaum, linkerTeilbaum);
return pBaum;
}
if((p->left != NULL) && (p->right != NULL)) {
struct tnode *rechterTeilbaum = p->right;
struct tnode *linkerTeilbaum = p->left;
free(p);
pBaum = addtree(pBaum, rechterTeilbaum);
pBaum = addtree(pBaum, linkerTeilbaum);
return pBaum;
}
}
int main() {
struct tnode *Baum = NULL;
struct tnode *tmpPos = NULL;
Baum = addelement(Baum, 10);
Baum = addelement(Baum, 30);
Baum = addelement(Baum, 20);
Baum = addelement(Baum, 35);
tmpPos = searchnode(Baum, 35);
if(tmpPos != 0) {
printf("Zu loeschendes Element: %d \n", tmpPos->content);
Baum = deletenode(tmpPos, Baum);
}
printf("Inorder Ausgabe\n");
printtree_inorder(Baum);
printf("Postorder Ausgabe\n");
printtree_postorder(Baum);
printf("Preorder Ausgabe\n");
printtree_preorder(Baum);
}

In the deletenode function, you aren't checking to see if p is NULL before you try to dereference it. Are you segfaulting?

Related

Pointer set to NULL but not in debugger

So I am working o AVL tree, however I cant seem to either get the delete function working nor freeing the tree right. The delete function segfaults everytime, but the free function segfaults when in the debugger.
Here is gdb's stack trace:
#0 0x00007fffd935a87a in msvcrt!_memicmp_l () from C:\WINDOWS\System32\msvcrt.dll
#1 0x0000000000402811 in isPresentRecurs (root=0xb756d0, searchedValue=0xb795b0 "aaa", found=0x61fcec) at ../.source/binTree.c:206
#2 0x00000000004027d6 in isPresent (root=0xb756d0, searchKey=0xb795b0 "aaa") at ../.source/binTree.c:200
#3 0x0000000000401c3d in main () at test.c:110
In my tests I check if the root has been set to NULL, which running it normally does finish however running it inside the debugger does not and instead goes into the else statement:
Minimal Example (test.c):
#include "binTree.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define TRACE 0
#define MAX_SEARCH_ITEMS 20
void fillTree(binTree **tree);
void fillSearchValues( char **valArray);
void fillTree(binTree** tree){
printf( "Constructing tree\n\n" );
char key[200] ="";
for(int j=1 ;j<4;j++ ){
memset(&key,0,199);
for(int i=0; i<26; i++){
for(int k = 0;k<j;k++) key[k]= i+'a';
Var value;
value.data = malloc(sizeof(varData));
value.data->iData = j;
value.type =INTEGER;
(*tree)->root= insert((*tree)->root,key,value);
if(TRACE) printf("key: %s, value: %d\n",(*tree)->root->key,(*tree)->root->value.data->iData);
}
}
(*tree)->nodeCount = getSizeBinaryTree((*tree)->root);
printf( "\n\nTree constructed\n\n" );
}
void fillSearchValues( char **valArray){
char key[200]="";
for(int j=1 ;j<4;j++ ){
memset(&key,0,199);
for(int i=0; i<26; i++){
if(i*j>MAX_SEARCH_ITEMS) break;
for(int k = 0;k<j;k++) key[k]= i+'a';
*(valArray+i*j) = strdup(key);
if (TRACE)printf ("%s read; %s inserted\n", key, valArray[i*j] );
}
}
}
int main(){
binTree *tree = createNewTree();
fillTree(&tree);
printTree(tree->root);
/* //Fails at delete
for(int i=0;i<26;i++){
char string = i+'a';
tree->root = Delete(tree->root,&string);
}*/
printf("\nFreeing Tree: \n=================================\n");
freeTree(tree->root);
if(tree->root==NULL) printf("Tree has been freed successfully\n");
else printf("Failed to free tree \n");
// searching after freeing
int found =0; int lost =0;
char *values[MAX_SEARCH_ITEMS];
fillSearchValues(values);
for(int i=0;i<MAX_SEARCH_ITEMS;i++){
if(isPresent(tree->root,values[i])){
if (TRACE)printf("found search value %s\n",values[i]);
found++;
}else{
lost++;
if(TRACE)printf("didnot find search value %s\n",values[i]);
}
}
printf("found %d of %d while cleared %d\n", found,MAX_SEARCH_ITEMS,lost);
free(tree);
return 0;
}
binTree.h:
#ifndef BINTREE_H
#define BINTREE_H
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define COUNT 10
typedef enum TYPE {INTEGER, FLOAT, CHARACTER} TYPE;
typedef union {
float fData;
int iData;
char cData;
} varData;
typedef struct Var{
varData * data;
TYPE type;
} Var;
typedef struct Node{
char* key;
Var value;
int height;
struct Node *left;
struct Node *right;
}Node;
typedef struct binTree{
Node *root;
unsigned int nodeCount;
}binTree;
int max(int a,int b);
binTree *createNewTree();
Node *newNode(char *key,Var value);
void freeTree(Node *node);
void freeNode(Node *node);
Node *insert(Node *node,char *key,Var value);
Node *rightRotate(Node *n);
Node *leftRotate(Node *n);
int height(Node *node);
int getBalance(Node *N);
void printTree(Node *root);
void printTreeS(Node *root,int space);
int isPresent(Node *root,char *searchKey);
void isPresentRecurs(Node *root,char *searchedValue,int *found);
Node *minValueNode(Node *node);
Node *search(Node *node,char *key);
Node *Delete(Node *root,char *key);
int getSizeBinaryTree(Node* root);
#endif
binTree.c
#include "binTree.h"
int max(int a, int b){
return (a > b)? a : b;
}
binTree* createNewTree(){
binTree *t = (binTree *) malloc(sizeof(binTree));
if(!t){
printf("Failed at allocationg tree\n");
exit(-1);
}
t->root = NULL;
return t;
}
Node* newNode(char * key,Var value){
Node *p = (Node*)malloc(sizeof(Node));
if(!p){
printf("Failed at allocationg node\n");
exit(-1);
}
p->key = strdup(key);
p->value = value;
p->left=p->right=NULL;
p->height = 1;
return p;
}
void freeTree(Node* node){
if (node==NULL) return;
freeTree(node->left);
freeTree(node->right);
freeNode(node);
node=NULL;
}
void freeNode(Node *node){
free(node->value.data);
node->value.data = NULL;
free(node->key);
node->key = NULL;
free(node);
node = NULL;
}
Node* insert(Node *node, char *key,Var value){
if (node == NULL) return newNode(key,value);
if ( strcasecmp(key ,node->key)<0) node->left = insert(node->left, key,value);
else if (strcasecmp(key ,node->key)>0) node->right = insert(node->right, key,value);
else if(strcasecmp(key,node->key)==0){
if(memcmp(&value.data,&node->value,sizeof(Var))!=0){
memcpy(&node->value,&value,sizeof(Var));
}
return node;
};
node->height = max(height(node->left),height(node->right))+1;
int balance = getBalance(node);
// Left Left Case
if (balance > 1 && strcasecmp(key, node->left->key)<0)
return rightRotate(node);
// Right Right Case
if (balance < -1 && strcasecmp(key, node->right->key)>0)
return leftRotate(node);
// Left Right Case
if (balance > 1 && strcasecmp(key, node->left->key)>0){
node->left = leftRotate(node->left);
return rightRotate(node);
}
// Right Left Case
if (balance < -1 && strcasecmp(key,node->right->key)<0){
node->right = rightRotate(node->right);
return leftRotate(node);
}
return node;
}
Node *rightRotate(Node *n){
Node *leftNode =n->left;
if(!leftNode) return n;
Node *rightOfLeft =leftNode->right;
leftNode->right = n;
n->left = rightOfLeft;
n->height = max(height(n->left), height(n->right)) + 1;
leftNode->height = max(height(leftNode->left), height(leftNode->right)) + 1;
return leftNode;
}
Node *leftRotate(Node *n){
Node *rightNode = n->right;
if(!rightNode) return n;
Node *leftOfright = rightNode->left;
rightNode->left = n;
n->right = leftOfright;
n->height = max(height(n->left), height(n->right)) + 1;
rightNode->height = max(height(rightNode->left), height(rightNode->right)) + 1;
return rightNode;
}
int height(Node *node){
if (!node) return 0;
return node->height;
}
int getBalance(Node *N){
if (N == NULL) return 0;
return height(N->left) - height(N->right);
}
void printTree(Node *root){
printTreeS(root, 0);
}
void printTreeS( Node *root, int space){
if (root == NULL)
return;
space += COUNT;
printTreeS(root->right, space);
printf("\n");
for (int i = COUNT; i < space; i++) printf(" ");
if (root->value.type == CHARACTER)printf("type: CHAR key: %s value: %s\n", root->key, root->value.data->cData);
if (root->value.type == INTEGER)printf("type: INT key: %s value: %d\n", root->key, root->value.data->iData);
if (root->value.type == FLOAT)printf("type: FLOAT key: %s value: %f\n", root->key, root->value.data->fData);
printTreeS(root->left, space);
}
int isPresent(Node* root, char* searchKey){
int found = 0;
isPresentRecurs( root, searchKey, &found );
return found;
}
void isPresentRecurs( Node *root,char *searchedValue,int* found ){
if (root) {
if (strcasecmp(root->key,searchedValue)==0)
*found = 1;
else {
isPresentRecurs(root->left, searchedValue, found);
if (!(*found))
isPresentRecurs( root->right, searchedValue, found);
}
}
}
Node * minValueNode(Node* node){
if(!node) return NULL;
if(node->left )return minValueNode(node->left);
return node;
}
Node *search(Node *node, char *key){
if (node == NULL || strcmp(node->key, key)==0)return node;
if (strcmp(node->key, key)<0) return search(node->right, key);
return search(node->left, key);
}
int getSizeBinaryTree(Node* root){
if (root) return 1 +getSizeBinaryTree( root->left ) + getSizeBinaryTree( root->right );
else return 0;
}
Node* Delete(Node* root,char *key) {
if (root==NULL) return root;
else if (strcasecmp(key ,root->key)>0) root->left =Delete(root->left,key);
else if (strcasecmp(key ,root->key)<0) root->right = Delete(root->right,key);
else {
if(root->right==NULL && root->left==NULL) {
free(root);
root = NULL;
}
else if(root->left!=NULL && root->right==NULL) {
Node* temp = root->left;
root = root->left;
freeNode(temp);
}
else if(root->right!=NULL && root->left==NULL) {
Node* temp = root->right;
root = root->right;
freeNode(temp);
}
else {
Node* temp = minValueNode(root->right);
root->key= temp->key;
root->value = temp->value;
root->right = Delete(root->right,temp->key);
}
}
if(root==NULL) return root;
root->height = 1 + max(height(root->left),height(root->right));
int balance = getBalance(root);
//Left Left Case
if(balance > 1 && getBalance(root->left) >=0) return rightRotate(root);
// Right Right Case
if(balance < -1 && getBalance(root->right) <=0) return leftRotate(root);
// Left Right Case
if(balance > 1 && getBalance(root->left) < 0) {
root->left = leftRotate(root->left);
return rightRotate(root);
}
//Right Left Case
if(balance < -1 && getBalance(root->right) > 0) {
root->right = rightRotate(root->right);
return leftRotate(root);
}
return root;
}
This is a mistake:
freeTree(tree->root);
if(tree->root==NULL) printf("Tree has been freed successfully\n");
else printf("Failed to free tree \n");
C uses pass-by-value, so it is not possible for freeTree to set tree->root to NULL.
The line node = NULL; inside the freeTree function sets the function parameter (which is a copy of the argument), it does not modify the argument in the calling context.
The function does free the pointed-to memory, which renders all pointers to that memory indeterminate, so the test tree->root == NULL actually causes undefined behaviour by using an indeterminate value.
Your compiler should warn about a dead-store for node=NULL; , if you do not see a warning then try turning up the warning and/or optimization level in your compiler, or running a static analyzer such as clang-tidy. freeNode has a similar issue.
To fix the problem, either change the calling code, e.g. freeTree(tree->root); tree->root = NULL;, or you will have to use pass-by-pointer, i.e. pass the address of the node you want to free.

C - Binary Search Tree, delete node

I have a question about my Code. "delete_single_node" does not work as it should. My procedure (to delete a node) is to find the node in the "head" tree, save the child nodes temporary, delete the node and all child nodes (in "head" tree) and merge the "head" tree with the temporary saved child nodes to a new correct binary tree.
I would like to stay with this procedure but I can't find my mistake.
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
struct tnode {
int content;
struct tnode *left;
struct tnode *right;
};
struct tnode* head;
void *malloc(size_t size);
struct tnode *talloc(void)
{
return(struct tnode*)malloc(sizeof(struct tnode));
}
/* delete a node with all child nodes*/
int deletenode(struct tnode *p)
{
if (p == NULL) return 0;
else
{
deletenode(p->left);
deletenode(p->right);
p->left = NULL;
p->right = NULL;
free(p);
return 0;
}
}
/* insert new node*/
struct tnode *addelement(struct tnode *p, int i) {
int cond;
if (p == NULL) {
p = talloc();
p->content = i;
p->left = p->right = NULL;
}
else if (p->content == i) {
return p;
}
else if (i < p->content)
p->left = addelement(p->left, i);
else
p->right = addelement(p->right, i);
return p;
}
/*merges two binary trees into one*/
struct tnode *addtree(struct tnode *top, struct tnode *p) {
if (p == NULL)
return top;
else
return addtree(addtree(addelement(top, p->content), p->right), p->left);
}
/*prints out tree*/
void showtree(struct tnode* nd)
{
if (nd == NULL)
return;
printf("ZZ %d", nd->content);
if (nd->left != NULL)
{
printf("left:%d", nd->left->content);
}
if (nd->right != NULL)
{
printf("right:%d\n", nd->right->content);
}
printf("\n");
showtree(nd->left);
showtree(nd->right);
}
/*removes connection to a node*/
void removeconnection(struct tnode *head, struct tnode *p) {
if (p->content > head->content) {
if (head->right == p)
{
head->right = NULL;
}
else
{
removeconnection(head->right, p);
}
}
if (p->content < head->content) {
if (head->left == p)
{
head->left = NULL;
}
else
{
removeconnection(head->left, p);
}
}
}
/*delete single node*/
struct tnode *delete_single_node(struct tnode *p, int content) {
struct tnode* temp2 = NULL;
struct tnode temp1;
struct tnode* temp4 = NULL;
struct tnode temp3;
if (p == NULL)
return NULL;
if (content > p->content)
{
p->right = delete_single_node(p->right, content);
}
else if (content < p->content)
{
p->left = delete_single_node(p->left, content);
}
else if (content == p->content)
{
if (p->left == NULL && p->right != NULL)
{
temp1.content = p->right->content;
temp1.right = p->right->right;
temp1.left = p->right->left;
temp2 = &temp1;
removeconnection(head, p);
deletenode(p);
head = addtree(head, temp2);
showtree(head);
}
else if (p->right == NULL && p->left != NULL)
{
temp1.content = p->left->content;
temp1.right = p->left->right;
temp1.left = p->left->left;
temp2 = &temp1;
removeconnection(head, p);
deletenode(p);
head = addtree(head, temp2);
showtree(head);
}
else if (p->right == NULL && p->left == NULL)
{
removeconnection(head, p);
deletenode(p);
showtree(head);
}
else
{
temp1.content = p->left->content;
temp1.right = p->left->right;
temp1.left = p->left->left;
temp2 = &temp1;
temp3.content = p->right->content;
temp3.right = p->right->right;
temp3.left = p->right->left;
temp4 = &temp3;
removeconnection(head, p);
deletenode(p);
head = addtree(head, temp2);
head = addtree(head, temp4);
showtree(head);
}
}
}
int main()
{
struct tnode* start = NULL;
int temp_int;
start = addelement(start, 5);
start = addelement(start, 6);
start = addelement(start, 2);
start = addelement(start, 9);
start = addelement(start, 3);
start = addelement(start, 2);
start = addelement(start, 1);
start = addelement(start, 7);
start = addelement(start, 8);
showtree(start);
printf("Which node to delete?\n");
scanf_s("%d", &temp_int);
head = start;
delete_single_node(start, temp_int);
return 0;
}

Pointer in function to linked list not updating element in 1 case

I am using a struct like this
struct infoM {
char* direction;
int key;
};
typedef struct nodeM{
struct infoM nodeInfo;
struct nodeM *next;
struct nodeM *prev;
} node;
typedef node list;
I have one function that returns the wanted node by a specific field
node * search(list *l, char* direction) {}
And this is my function to remove elements from the list
int delete(list *l, char* direction) {
node *tmp = search(l, direction);
if (tmp != NULL) {
node *ant = tmp->prev;
node *seg = tmp->next;
if (seg != NULL) {
if (ant != NULL) {
ant->next = seg;
seg->prev = ant;
free(tmp);
return 1;
} else { //prev null
seg->prev = NULL;
*l = *seg;
tmp = NULL;
free(tmp);
return 1;
}
} else { //next null
if (ant == NULL) {
l->nodeInfo.key = somevalue;
l->next = NULL;
l->prev = NULL;
return 1;
} else {
printf("Here is the problem\n");
ant->next = NULL;
free(tmp);
return 1;
}
}
} else { //tmp nulo
perror("Error delete : node null\n");
return 0;
}
}
If I have 4 elements in the list, 1234 and I delete first first element everything is okay and returns 234. If I delete the last element it returns 23 seems to work great. But if I try to delete the last element now the function does nothing despite being the same case that when it is 234 and I don't understand why. The list is not being updated.
In the main I am using the list like this :
list a;
delete(&a, "whatever");
What am I doing wrong ?
This is the code for search
node * createnode(){
node *tmp = (node *) malloc (sizeof(node));
return tmp;
}
node * search(list *l, char* direction) {
node *tmp = createnode();
if (l->nodeInfo.key == 777) {
perror("Error search: empty list\n");
return NULL;
}
tmp=l;
while((strcmp(direction, tmp->nodeInfo.direction) !=0) && (tmp->next != NULL)) {
tmp = tmp->next;
}
if (strcmp(direction, tmp->nodeInfo.direction) == 0) {
return tmp;
} else {
perror("Error search: element not found\n");
return NULL;
}
}

Binary Search Tree node deletion error

I've created my binary search tree and gave the pointer to the node which I want to delete into my *p.
The delete method is supposed to be deleting the node which is pointed at by *p and should add the subtrees with addtree to my root. *pBaum is the pointer which points to my root.
However im getting an error message called "conflict types" on addtree everytime I declare
Baum = addtree(Baum, p->right);
I also get a warning "assignment makes pointer from integer without a cast"
My struct contains left & right pointer to the subtrees and a pointer to the content.
struct tnode
{
int content;
struct tnode *left; /* linker Teilbaum */
struct tnode *right; /* rechter Teilbaum */
};
// Deletes the node where *p is pointing at
struct tnode *deletenode(struct tnode *p, struct tnode *pBaum)
{
struct tnode *Baum = pBaum;
if ((p->left == NULL) && (p->right == NULL))
{
free(p);
}
if ((p->left == NULL) && (p->right != NULL))
{
Baum = addtree(Baum, p->right);
free(p);
}
if ((p->right == NULL) && (p->left !=NULL))
{
Baum = addtree(Baum, p->left);
free(p);
}
if ((p->left != NULL) && (p->right !=NULL))
{
Baum = addtree(Baum, p->right);
Baum = addtree(Baum, p->left);
free(p);
}
return Baum;
}
// Adds the Subtrees to my root
struct tnode *addtree(struct tnode *top, struct tnode *p)
{
if (p == NULL)
return top;
else
return addtree(addtree(addelement(top, p->content),p-> right), p->left);
// Adds a node to my Tree
struct tnode *addelement(struct tnode *p, int i)
{
int cond;
if (p == NULL)
{
p = talloc(); /* make a new node */ p->content = i;
p->left =p->right =NULL;
}
else if (p->content == i)
{
return p;
}
else if (i < p->content) /* goes into left subtree */ p->left =addelement(p->left, i);
else /* goes into right subtree */ p->right = addelement(p->right, i);
return p;
}
// Looks for the node which is supposed to get deleted and returns a pointer to it
struct tnode *searchnode(struct tnode *p, int nodtodelete)
{
if (p == NULL)
{
printf("Baum ist leer oder Element nicht vorhanden \n");
return NULL;
}
if ( p -> content == nodtodelete)
{
return p;
}
if (p->content < nodtodelete)
{
return searchnode (p->right, nodtodelete);
}
if (p->content > nodtodelete)
{
return searchnode(p->left, nodtodelete);
}
}
}
int main()
{
struct tnode *Baum = NULL;
struct tnode *tmpPos = NULL;
Baum = addelement (Baum, 32);
Baum = addelement(Baum, 50);
Baum = addelement(Baum, 60);
tmpPos = searchnode(Baum,50);
Baum = deletenode(tmpPos, Baum);
}
Have you declare the function before function call in code ? i declare the addtree and addelement functions on top of the file and error for conflict types is gone.
I'm not sure if this is due to you only including partial code, but you addtree function is not complete:
struct tnode *addtree(struct tnode *top, struct tnode *p)
{
if (p == NULL)
return top;
else
return addtree(addtree(addelement(top, p->content),p-> right), p->left);
This function needs to be ended with a bracket:
struct tnode *addtree(struct tnode *top, struct tnode *p)
{
if(p == NULL)
return top;
return addtree(addtree(addelement(top, p->content), p->right), p->left);
}
To make it so the compiler doesn't potentially complain about not returning a value in a non void function it's best to get rid of the else as well.

Word occurrences and line numbers

I'm making a program that generates a text file that contains the occurrences of words and the line number of each occurrence of another text file. I'm using an AVL tree struct that contains the word and a linked list struct that contains one node for each line number. Here are the struct definitions:
struct llnode {
struct llnode *next;
int num;
};
struct node {
char *word;
struct llnode *head;
struct node *left;
struct node *right;
int height;
};
I get a segmentation fault when I try to print to the text file using the below functions.
void listprint(struct llnode *p) {
if(p->next == NULL) {
printf("%d", p->num);
} else {
printf("%d, ", p->num);
listprint(p->next);
}
}
void treeprint(struct node *p) {
if(p != NULL) {
treeprint(p->left);
printf("%s: ", p->word);
listprint(p->head);
treeprint(p->right);
}
}
Specifically the problem is this line
if(p->next == null) {
gdb gives me
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000000
Thanks for your help.
Edit:
void listinsert(struct llnode *p) {
struct llnode *prev = p;
while(p != NULL) {
prev = p;
p = p->next;
}
p = lalloc();
p->num = line;
p->next = NULL;
prev->next = p;
struct node *addtree(struct node *p, char *w) {
int cond;
if(p == NULL) {
p = talloc();
p->head = NULL;
p->word = mystrdup(w);
p->head = listinsert(p->head);
p->left = p->right = NULL;
} else if((cond = strcmp(w, p->word)) == 0) {
listinsert(p->head);
} else if(cond < 0) {
p->left = addtree(p->left, w);
if(height(p->left)-height(p->right) == 2) {
if(strcmp(w, p->left->word) < 0) {
p = singleleft(p);
} else {
p = doubleleft(p);
}
}
} else {
p->right = addtree(p->right, w);
if(height(p->right)-height(p->left) == 2) {
if(strcmp(w, p->right->word) > 0) {
p = singleright(p);
} else {
p = singleleft(p);
}
}
}
return p;
int getword(char *word, int lim) {
int c;
char *w = word;
while(isspace(c = getch()));
if(c == '\n') {
line++;
}
if(c != EOF) {
*w++ = c;
}
if(!isalpha(c)) {
*w = '\0';
return c;
}
for( ; --lim > 0; w++) {
if(!isalnum(*w = getch())) {
ungetch(*w);
break;
}
}
*w = '\0';
return word[0];
In listprint, you are not checking if p is null before checking if p->next is null.
Try this.
llnode* listinsert(struct llnode *p) {
struct llnode *prev = p;
if( NULL == prev ) {
prev = lalloc();
prev->num= line;
prev->next = NULL;
return prev;
}
while(prev->next != NULL) {
prev = prev->next;
}
prev->next = lalloc();
prev = prev->next;
prev->num = line;
prev->next = NULL;
return p;
}

Resources