Segmentation Fault when Deleting in an AVL Tree? - c

I seem to be get a strange segmentation fault when I am attempting to delete in my implementation of an AVL Tree holding strings. The problem comes in the fact that I seem to only get segmentation fault when I am deleting a leaf node. Here is the code for deletion, is there anywhere that could create a problem? According to GDB the error is the function deleteBalance.
struct node{
char *word;
int balance;
struct node *children[2];
};
struct tree{
struct node *root;
int numElements;
};
struct tree *treeCreate(void){
struct tree *s = malloc(sizeof(struct tree));
s->root = NULL;
s->numElements = 0;
return s;
}
char *stringDuplicate (const char *s) {
char *d = malloc (strlen (s) + 1);
if (d == NULL) return NULL;
strcpy (d,s);
return d;
}
size_t treeSize(const struct tree *s){
return s->numElements;
}
struct node *make_node(char *word){
struct node *temp = malloc(sizeof(*temp));
if(temp != NULL){
temp->word = word;
temp->children[0] = temp->children[1] = NULL;
temp->balance = 0;
}
return temp;
}
void adjustBalance(struct node *root, int direction, int temp_bal){
struct node *temp1 = root->children[direction];
struct node *temp2 = temp1->children[!direction];
if(temp2->balance == 0){
root->balance = temp1->balance = 0;
}else if(temp2->balance == temp_bal){
root->balance = -temp_bal;
temp1->balance = 0;
}else{
root->balance = 0;
temp1->balance = temp_bal;
}
temp2->balance = 0;
}
struct node *singleRotation(struct node *root, int direction){
struct node *temp = root->children[!direction];
root->children[!direction] = temp->children[direction];
temp->children[direction] = root;
return temp;
}
struct node *doubleRotation(struct node *root, int direction){
struct node *temp = root->children[!direction]->children[direction];
root->children[!direction]->children[direction] = temp->children[!direction];
temp->children[!direction] = root->children[!direction];
root->children[!direction] = temp;
temp = root->children[!direction];
root->children[!direction] = temp->children[direction];
temp->children[direction] = root;
return temp;
}
struct node *insertBalance(struct node *root, int direction){
struct node *temp = root->children[direction];
int temp_bal;
if(direction == 0){
temp_bal = -1;
}else{
temp_bal = 1;
}
if(temp->balance == temp_bal){
root->balance = temp->balance = 0;
root = singleRotation(root, !direction);
}else{
adjustBalance(root, direction, temp_bal);
root = doubleRotation(root, !direction);
}
return root;
}
struct node *insertRecursive(struct node *root, char *word, int *done){
if(root == NULL){
root = make_node(word);
}
else{
int direction = strcmp(word, root->word);
if(direction > 0){
direction = 1;
}else if(direction < 0){
direction = 0;
}
root->children[direction] = insertRecursive(root->children[direction], word, done);
if(!*done){
if(direction == 0){
root->balance += -1;
}else{
root->balance += 1;
}
if(root->balance == 0){
*done = 1;
}else if(abs(root->balance) > 1){
root = insertBalance(root, direction);
*done = 1;
}
}
}
return root;
}
void treeInsert(struct tree *tree, const char *word){
int done = 0;
char *newWord = stringDuplicate(word);
tree->root = insertRecursive(tree->root, newWord, &done);
}
struct node *deleteBalance(struct node *root, int direction, int *done){
struct node *temp = root->children[!direction];
int temp_bal;
if(direction == 0){
temp_bal = -1;
}else{
temp_bal = 1;
}
if(temp->balance == -temp_bal){ //ERROR OCCURRING HERE
root->balance = temp->balance = 0;
root = singleRotation(root, direction);
}else if(temp->balance == temp_bal){
adjustBalance(root, !direction, -temp_bal);
root = doubleRotation(root, direction);
}else{
root->balance = -temp_bal;
temp->balance = temp_bal;
root = singleRotation(root, direction);
*done = 1;
}
return root;
}
struct node *deleteRecursion(struct node *root, char *word, int *done){
if(root != NULL){
int direction;
if(strcmp(word, root->word) == 0){
if(root->children[0] == NULL || root->children[1] == NULL){
struct node *temp;
if(root->children[0] == NULL){
direction = 1;
}else{
direction = 0;
}
temp = root->children[direction];
free(root);
return temp;
}
else{
struct node *heir = root->children[0];
while(heir->children[1] != NULL){
heir = heir->children[1];
}
root->word = heir->word;
word = heir->word;
}
}
direction = strcmp(word, root->word);
if(direction > 0){
direction = 1;
}else if(direction < 0){
direction = 0;
}
root->children[direction] = deleteRecursion(root->children[direction], word, done);
if(!*done){
if(direction == 0){
root->balance += -1;
}else{
root->balance += 1;
}
if(abs(root->balance) == 1){
*done = 1;
}else if(abs(root->balance) > 1){
root = deleteBalance(root, direction, done);
}
}
}
return root;
}
void treeDelete(struct tree *tree, const char *word){
int done = 0;
char *newWord = stringDuplicate(word);
tree->root = deleteRecursion(tree->root, newWord, &done);
}
Edit: I have added all the functions I use, both insert and delete.

Related

How to insert and display elements to a Dequeue using linked implementation in C

I tried a basic dequeue program in c using linked implementation. But it shows some error with the function that is used to insert element to the dequeue. Also i want to display the element in the dequeue. Below is the code i tried. The CLI doesn't show any output when running the code. Due to the error in the Insert function i'm not sure whether the delete functions are also correct or incorrect.
#include<stdio.h>
#include<stdlib.h>
typedef int DeQueueElement;
typedef enum{FALSE,TRUE} Boolean;
typedef struct node{
DeQueueElement entry;
struct node *next, *prev;
}Node;
typedef struct dequeue{
int count;
Boolean full;
Node *front;
Node *rear;
}DeQueue;
void CreateDeQueue(DeQueue *dq){
dq->count = 0;
dq->full = FALSE;
dq->front = dq->rear = -1;
}
Boolean IsEmpty(DeQueue *dq){
return (dq->front == NULL && dq->rear == NULL);
}
Boolean IsFull(DeQueue *dq){
return(dq->full);
}
void InsertRear(DeQueueElement x, DeQueue *dq){
Node *np;
np = (Node* )malloc(sizeof(Node));
if(np == NULL){
printf("Not enough space\n");
}
else{
if(dq->rear == NULL)
dq->front = dq->rear = np;
else{
np->prev = dq->rear;
dq->rear->next = np;
dq->rear = NULL;
np->next = np;
np->entry = x;
}
}
}
void InsertFront(DeQueueElement x, DeQueue *dq){
Node *np;
np = (Node* )malloc(sizeof(Node));
if(np == NULL)
printf("Not enough space\n");
else{
if(dq->front == NULL)
dq->rear = dq->front = np;
else{
np->next = dq->front;
dq->front->prev = np;
dq->front = np;
np->prev = NULL;
np->entry = x;
}
}
}
void DeleteFront(DeQueue *dq){
if(dq->front == NULL)
printf("Underflow\n");
else{
Node *temp;
temp = dq->front;
dq->front = dq->front->next;
if(dq->front == NULL)
dq->rear = NULL;
else
dq->front->prev = NULL;
free(temp);
}
}
void DeleteRear(DeQueue *dq){
if(dq->front == NULL)
printf("Underflow\n");
else{
Node *temp;
temp = dq->rear;
dq->rear = dq->rear->prev;
if(dq->rear == NULL)
dq->front == NULL;
else
dq->rear->next = NULL;
free(temp);
}
}
void display(DeQueue *dq) {
Node *temp;
if (dq->front->next == dq->rear) {
printf("Queue is empty\n");
return;
}
temp = dq->front->next;
while (temp != dq->rear) {
printf("%d", temp->entry);
temp = temp->next;
}
printf("\n");
}
int main(){
DeQueue dq;
CreateDeQueue(&dq);
InsertFront(21,&dq);
InsertFront(1,&dq);
InsertFront(221,&dq);
InsertRear(23,&dq);
InsertRear(36,&dq);
display(&dq);
}
The code has some errors and I try to correct them and comment where I made the changes.
The problems are in CreateDeQueue, InsertFront, InsertRear and display functions.
void CreateDeQueue(DeQueue *dq){
dq->count = 0;
dq->full = FALSE;
// dq->front = dq->rear = -1;
// Change 0: It should be NULL or 0 not -1
dq->front = NULL;
dq->rear = NULL;
}
void InsertRear(DeQueueElement x, DeQueue *dq){
Node *np;
np = (Node* )malloc(sizeof(Node));
if(np == NULL){
printf("Malloc failed\n");
}
else{
np->entry = x;
np->next = NULL;
np->prev = NULL;
if(dq->rear == NULL)
dq->front = dq->rear = np;
else{
np->prev = dq->rear;
dq->rear->next = np;
//dq->rear = NULL;
//Change 1: Why dq->rear to NULL it should point to valid mem location
dq->rear = np;
}
dq->count++;
}
}
void InsertFront(DeQueueElement x, DeQueue *dq){
Node *np;
np = (Node* )malloc(sizeof(Node));
if(np == NULL)
printf("Malloc failed. \n");
else{
//Change 3: Initialize the newly created struct Node, np
np->entry = x;
np->next = NULL;
np->prev = NULL;
if(dq->front == NULL)
dq->rear = dq->front = np;
else{
np->next = dq->front;
dq->front->prev = np;
dq->front = np;
}
dq->count++;
}
}
void display(DeQueue *dq) {
Node *temp;
if (dq->front->next == dq->rear) {
printf("Queue is empty\n");
return;
}
temp = dq->front;
// Change 4: Checking temp against dq->rear is not logical i guess
// temp should not be NULL. Printing from the front
while (temp!=dq->rear->next) {
printf("%d ", temp->entry);
printf("\n");
temp = temp->next;
}
}

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;
}

Red Black Tree - fixTree implementtation doesn't work correctly

I've got the problem with display RedBlack Tree after insertion a few numbers.
Probably fixTree function contains some errors (after inserting numbers is displayed only the first number = 38).
Does anyone have an idea what is wrong?
#include <stdio.h>
#include <stdlib.h>
#define swap(type, i, j) {type t = i; i = j; j = t;}
typedef enum COLOR{
RED,
BLACK
} NodeColor;
typedef struct BST{
struct BST *up, *left, *right;
int key, color;
} RedBlackTree;
RedBlackTree *tree = NULL;
RedBlackTree *createNode(int key){
RedBlackTree *temp;
temp = (RedBlackTree*) malloc(sizeof(RedBlackTree));
temp->left = NULL;
temp->right = NULL;
temp->key = key;
temp->color = RED;
return temp;
}
void rotateLeft(RedBlackTree *root, RedBlackTree *temp){
RedBlackTree *rightSon = temp->right;
temp->right = rightSon->left;
if (temp->right != NULL){
temp->right->up = temp;
}
rightSon->up = temp->up;
if (temp->up == NULL){
root = rightSon;
}
else if (temp == temp->up->left){
temp->up->left = rightSon;
}
else{
temp->up->right = rightSon;
}
rightSon->left = temp;
temp->up = rightSon;
}
void rotateRight(RedBlackTree *root, RedBlackTree *temp){
RedBlackTree *leftSon = temp->left;
temp->left = leftSon->right;
if (temp->left != NULL){
temp->left->up = temp;
}
leftSon->up = temp->up;
if (temp->up == NULL){
root = leftSon;
}
else if (temp == temp->up->left){
temp->up->left = leftSon;
}
else{
temp->up->right = leftSon;
}
leftSon->right = temp;
temp->up = leftSon;
}
void fixTree(RedBlackTree *root, RedBlackTree *temp){
RedBlackTree *parent = NULL;
RedBlackTree *grandparent = NULL;
while ((temp != root) && (temp->color != BLACK) && (temp->up->color == RED)){
parent = temp->up;
grandparent = temp->up->up;
if (parent == grandparent->left){
RedBlackTree *uncle = grandparent->right;
if (uncle != NULL && uncle->color == RED){
grandparent->color = RED;
parent->color = BLACK;
uncle->color = BLACK;
temp = grandparent;
}
else{
if (temp == parent->right){
rotateLeft(root, parent);
temp = parent;
parent = temp->up;
}
rotateRight(root, grandparent);
swap(int, parent->color, grandparent->color);
temp = parent;
}
}
else{
RedBlackTree *uncle = grandparent->left;
if ((uncle != NULL) && (uncle->color == RED)){
grandparent->color = RED;
parent->color = BLACK;
uncle->color = BLACK;
temp = grandparent;
}
else{
if (temp == parent->left){
rotateRight(root, parent);
temp = parent;
parent = temp->up;
}
rotateLeft(root, grandparent);
swap(int, parent->color, grandparent->color);
temp = parent;
}
}
}
root->color = BLACK;
}
RedBlackTree *insertNode(RedBlackTree *root, RedBlackTree *temp){
if (root == NULL){
return temp;
}
if (temp->key < root->key){
root->left = insertNode(root->left, temp);
root->left->up = root;
}
else if (temp->key > root->key){
root->right = insertNode(root->right, temp);
root->right->up = root;
}
return root;
}
void insert(int key){
RedBlackTree *temp = createNode(key);
tree = insertNode(tree, temp);
fixTree(tree, temp);
}
void printTree(RedBlackTree *root){
if (root){
printTree(root->left);
printf("%d %s\n", root->key, root->color == 0 ? "RED" : "BLACK");
printTree(root->right);
}
}
int main(){
insert(38);
insert(31);
insert(22);
insert(8);
insert(20);
insert(5);
insert(10);
insert(9);
insert(21);
insert(27);
insert(29);
insert(25);
insert(28);
printTree(tree);
return 0;
}
void fixTree(RedBlackTree *root, RedBlackTree *temp)
You pass the address of the root by value, so any change to root inside fixTree will not be visible in the calling code. In particular rotateLeft and rotateRight, into where you again copy the address, will not modify the variable in the calling code.
You need to pass a pointer to the root pointer. Meaning your prototype should be
void fixTree(RedBlackTree **p_root, RedBlackTree *temp)
An naturally the operation adjusted so they are preformed on *p_root. Such as the following line in rotateLeft:
*p_root = rightSon;

Valgrind Error in Freeing AVL Tree

I've made an AVL Tree for strings, and the tree itself works well: Insertion, Deletion, Search are all working well. However, valgrind is giving me an error. Valgrind says the error is in my stringDuplicate function (I have made a comment on the specific line number where valgrind points it out) and it is when this stringDuplicate function is called by my treeInsert function (I have made a comment where treeInsert calls stringDuplicate). Can someone help me find my valgrind error?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "tree.h"
//NODES OF TREE
struct node{
char *word;
int balance;
struct node *children[2];
};
//STRUCT TREE WHICH CONTAINS A POINTER TO THE ROOT AND NUMBER OF ELEMENTS
struct tree{
struct node *root;
size_t numElements;
};
//MALLOC SPACE FOR TREE
struct tree *treeCreate(void){
struct tree *s = malloc(sizeof(struct tree));
s->root = NULL;
s->numElements = 0;
return s;
}
//CREATE A DUPLICATE OF THE STRINGS TO BE INSERTED/DELETED
char *stringDuplicate (const char *s) {
char *d = malloc (strlen (s) + 1); //VALGRIND POINTS TO THIS LINE FOR ERROR
if (d == NULL) return NULL;
strcpy (d,s);
return d;
}
//RETURN THE SIZE OF THE TREE
size_t treeSize(const struct tree *s){
return s->numElements;
}
//CREATE A NEW NODE OF THE TREE
struct node *make_node(char *word){
struct node *temp = malloc(sizeof(struct node));
if(temp != NULL){
temp->word = word;
temp->children[0] = temp->children[1] = NULL;
temp->balance = 0;
}
return temp;
}
//CHANGE THE BALANCE OF NODE/NODES IN THE TREE
void adjustBalance(struct node *root, int direction, int temp_bal){
struct node *temp1 = root->children[direction];
struct node *temp2 = temp1->children[!direction];
if(temp2->balance == 0){
root->balance = temp1->balance = 0;
}else if(temp2->balance == temp_bal){
root->balance = -temp_bal;
temp1->balance = 0;
}else{
root->balance = 0;
temp1->balance = temp_bal;
}
temp2->balance = 0;
}
//SINGLE ROTATION OF TREE
struct node *singleRotation(struct node *root, int direction){
struct node *temp = root->children[!direction];
root->children[!direction] = temp->children[direction];
temp->children[direction] = root;
return temp;
}
//DOUBLE ROTATION OF TREE
struct node *doubleRotation(struct node *root, int direction){
struct node *temp = root->children[!direction]->children[direction];
root->children[!direction]->children[direction] = temp->children[!direction];
temp->children[!direction] = root->children[!direction];
root->children[!direction] = temp;
temp = root->children[!direction];
root->children[!direction] = temp->children[direction];
temp->children[direction] = root;
return temp;
}
//CHANGE THE BALANCE OF NODES WHEN INSERTING
struct node *insertBalance(struct node *root, int direction){
struct node *temp = root->children[direction];
int temp_bal;
if(direction == 0){
temp_bal = -1;
}else{
temp_bal = 1;
}
if(temp->balance == temp_bal){
root->balance = temp->balance = 0;
root = singleRotation(root, !direction);
}else{
adjustBalance(root, direction, temp_bal);
root = doubleRotation(root, !direction);
}
return root;
}
//INSERT INTO TREE RECURSIVELY
struct node *insertRecursive(struct node *root, char *word, int *flag){
if(root == NULL){
root = make_node(word);
}
else{
//IF word < root->word, WE NEED TO GO LEFT AND direction < 0
//IF word > root->word, WE NEED TO GO RIGHT AND direction > 0
int direction = strcmp(word, root->word);
if(direction > 0){
direction = 1;
}else if(direction < 0){
direction = 0;
}
root->children[direction] = insertRecursive(root->children[direction], word, flag);
if(!*flag){
if(direction == 0){
root->balance += -1;
}else{
root->balance += 1;
}
if(root->balance == 0){
*flag = 1;
}else if(abs(root->balance) > 1){
root = insertBalance(root, direction);
*flag = 1;
}
}
}
return root;
}
//SEARCH FOR A STRING IN TREE: 1 IF IN TREE, 0 IF NOT
int searchTree(struct node *root, char *word){
int flag = 0;
struct node *current = root;
while(!flag){
if(current){
int direction = strcmp(word, current->word);
if(direction == 0){
flag = 1;
break;
}else if(direction > 0){
direction = 1;
}else{
direction = 0;
}
current = current->children[direction];
}else{
break;
}
}
return flag;
}
//INSERT NEW ELEMENT INTO TREE
void treeInsert(struct tree *tree, const char *word){
char *newWord = stringDuplicate(word);
int flag = searchTree(tree->root, newWord);
int temp = 0;
if(flag == 0){
tree->root = insertRecursive(tree->root, newWord, &temp);
tree->numElements = tree->numElements + 1;
}
}
//CHANGE THE BALANCE OF NODES WHEN DELETING FROM TREE
struct node *deleteBalance(struct node *root, int direction, int *flag){
struct node *temp = root->children[!direction];
int temp_bal;
if(direction == 0){
temp_bal = -1;
}else{
temp_bal = 1;
}
if(temp->balance == -temp_bal){
root->balance = temp->balance = 0;
root = singleRotation(root, direction);
}else if(temp->balance == temp_bal){
adjustBalance(root, !direction, -temp_bal);
root = doubleRotation(root, direction);
}else{
root->balance = -temp_bal;
temp->balance = temp_bal;
root = singleRotation(root, direction);
*flag = 1;
}
return root;
}
//DELETE A STRING FROM TREE ITERATIVELY
void treeDelete(struct tree *tree, const char *word){
if(tree->root != NULL){
char *newWord = stringDuplicate(word);
struct node *iterator, *ancestor_array[32];
int ancestor_direction[32];
int current_index = 0;
int flag = 0;
iterator = tree->root;
for(;;){
if(iterator == NULL){
return;
}else if(strcmp(newWord, iterator->word) == 0){
tree->numElements = tree->numElements - 1;
break;
}
int direction = strcmp(word, iterator->word);
if(direction > 0){
direction = 1;
}else if(direction < 0){
direction = 0;
}
ancestor_direction[current_index] = direction;
ancestor_array[current_index++] = iterator;
iterator = iterator->children[ancestor_direction[current_index - 1]];
}
if(iterator->children[0] == NULL || iterator->children[1] == NULL){
int dir = iterator->children[0] == NULL;
if(current_index != 0){
ancestor_array[current_index - 1]->children[ancestor_direction[current_index - 1]] = iterator->children[dir];
}else{
tree->root = iterator->children[dir];
}
free(iterator);
}else{
struct node *heir = iterator->children[1];
ancestor_direction[current_index] = 1;
ancestor_array[current_index++] = iterator;
while(heir->children[0] != NULL){
ancestor_direction[current_index] = 0;
ancestor_array[current_index++] = heir;
heir = heir->children[0];
}
iterator->word = heir->word;
ancestor_array[current_index - 1]->children[ancestor_array[current_index - 1] == iterator] = heir->children[1];
free(heir);
}
while(--current_index >= 0 && !flag){
ancestor_array[current_index]->balance += ancestor_direction[current_index] != 0 ? -1 : 1;
if(abs(ancestor_array[current_index]->balance) == 1){
break;
}else if(abs(ancestor_array[current_index]->balance) > 1){
ancestor_array[current_index] = deleteBalance(ancestor_array[current_index], ancestor_direction[current_index], &flag);
if(current_index != 0){
ancestor_array[current_index - 1]->children[ancestor_direction[current_index - 1]] = ancestor_array[current_index];
}else{
tree->root = ancestor_array[0];
}
}
}
}
return;
}
//FREE TREE
void treeDestroyHelper(struct node *root){
if(root == NULL){
return;
}
if(root->children[0] == NULL && root->children[1] == NULL){
free(root->word);
free(root);
}else if(root->children[0] == NULL && root->children[1] != NULL){
treeDestroyHelper(root->children[1]);
free(root->word);
free(root);
}else if(root->children[0] != NULL && root->children[1] == NULL){
treeDestroyHelper(root->children[0]);
free(root->word);
free(root);
}else{
treeDestroyHelper(root->children[0]);
treeDestroyHelper(root->children[1]);
free(root->word);
free(root);
}
}
//FREE TREE
void treeDestroy(struct tree *s){
treeDestroyHelper(s->root);
free(s);
}
edit: Just wanted to add the comment in case anyone was wondering that tree.h is simply the function headers I am using.
You duplicate the word in treeDelete() and forget to free it. Duplicating is unnecessary there. valgrind complains that memory allocated by stringDuplicate() is not freed.
Incidentally, this function name is confusing, you should use treeDeleteString. Same for treeInsert -> treeInsertString, and some other ones.
Edit: you also forget to free the string in treeDelete() before free(iterator); and free(heir);. I cannot tell if the logic in treeDelete() is correct from a quick analysis of your code, but these missing free() are definitely causing memory to be lost and reported as such by valgrind.

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