C - Binary Search Tree, delete node - c

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

Related

Singly Linked List head of 0

I got problem with Singly Linked List problem.
When i inserted something in front of head. head is always have 0 of data.
I think init_list() function is something wrong. I think head of 0 is from randomly initialized data.
anything is fine without head 0 problem.
I'm sure that initializing method is wrong. But I don't know how to solve it..
Here is my I/0 and Desired Output
Input
2
insert 0 1
size
Output I got
1->0->NULL
2
1->0->NULL
Desired Output
1->NULL
1
1->NULL
Here is My Code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef int Element;
typedef struct LinkedNode {
Element data;
struct LinkedNode* link;
} Node;
Node* head;
void init_list() {
head = (Node*)malloc(sizeof(Node));
head->link = NULL;
}
int is_empty() {
if (head == NULL) return 1;
else return 0;
}
Node* get_entry(int pos)
{
Node* p = head;
int i;
for (i = 0; i < pos; i++, p=p->link){
if (p == NULL) return NULL;
}
return p;
}
int size()
{
Node* p;
int count = 0;
for (p = head; p != NULL; p = p->link)
count++;
return count;
}
void replace(int pos, Element val)
{
Node* node = get_entry(pos);
if (node != NULL)
node->data = val; // replace
}
Node* search_list(Element val)
{
Node* p;
for (p = head; p != NULL; p = p->link)
if (p->data == val) return p;
return NULL;
}
void insert_next(Node * before, Node * node)
{
if (node != NULL) {
node->link = before->link;
before->link = node;
}
}
void insert(int pos, Element val)
{
Node* new_node, * prev;
new_node = (Node*)malloc(sizeof(Node));
new_node->data = val;
if (pos == 0) {
new_node->link = head;
head = new_node;
}
else {
prev = get_entry(pos-1);
if (prev != NULL)
insert_next(prev, new_node);
else free(new_node);
}
}
Node * remove_next(Node * prev)
{
Node* removed = prev->link;
if (removed != NULL) {
prev->link = removed->link;
}
return removed;
}
void delete(int pos)
{
Node* prev, * removed;
if (pos == 0 && is_empty() == 0) {
removed = get_entry(pos);
head = head->link;
free(removed);
}
else {
prev = get_entry(pos-1);
if (prev != NULL) {
remove_next(prev);
free(removed);
}
}
}
void clear_list()
{
while (is_empty() == 0)
delete(0);
}
void print_list()
{
Node* p;
for (p = head; p != NULL; p = p->link)
printf("%d->", p->data);
printf("NULL\n");
}
Node * concat_list(Node * new_node)
{
if(is_empty()) return new_node;
else if(new_node == NULL) return new_node;
else{
Node* p;
p = head;
while (p->link != NULL) {
p = p->link;
}
p->link = new_node;
return head;
}
}
int main(void)
{
Element num;
int pos;
int n, i, j, len;
char c[15];
Node* tmp_head= NULL;
Node* new_head= NULL;
init_list();
scanf("%d", &n);
for (i = 0; i < n; i++)
{
scanf("%s", c);
if (strcmp(c, "insert") == 0) { scanf("%d %d\n",&pos, &num); insert(pos,num); print_list();}
else if (strcmp(c, "delete") == 0) { scanf("%d\n", &pos); delete(pos); print_list();}
else if (strcmp(c, "size") == 0) {printf("%d\n", size()); print_list();}
else if (strcmp(c, "empty") == 0) {printf("%d\n", is_empty()); print_list();}
else if (strcmp(c, "getEntry") == 0) { scanf("%d\n", &pos); printf("%d\n", get_entry(pos)->data); print_list();}
else if (strcmp(c, "search_list") == 0) { scanf("%d\n", &num); printf("%d\n", search_list(num)->data); print_list();}
else if (strcmp(c, "replace") == 0) { scanf("%d %d\n", &pos, &num); replace(pos,num); print_list();}
else if (strcmp(c, "concat_list") == 0) {
tmp_head = head;
init_list();
scanf("%d", &len);
for (j = 0; j < len; j++)
{
scanf("%d %d\n",&pos, &num); insert(pos,num);
}
printf("new_node: ");
print_list();
new_head = head;
head = tmp_head;
head = concat_list(new_head);
print_list();
}
else printf("error\n");
}
return 0;
}
The basic problem is that within init_list, the code only initializes link but not data. I'd suggest instead that you initialize head to NULL and simply use insert to create nodes.

Insert function for every binary tree

If i have for example 2 binary trees:
typedef struct node {
int key;
struct node *left, *right;
} node;
node* root1
node* root2
I've tried this function to insert nodes:
void insert(node* root, int key) {
node *p, *q;
p = (node*) calloc(1,sizeof(node);
p->key = key;
if (root == NULL) {
root = p;
return;
}
q = root;
for (;;) {
if (key < q->key) {
if (q->left == 0) {
q->left = p;
return;
} else q = q->left;
} else if (key > q->key) {
if (q->right == 0) {
q->right = p;
return;
} else q = q->right;
} else {
free(p);
return;
}
}
}
but after call insert(root1,10) the tree root1 remains untouched. I suppose it happens because root variable inside function is changed locally.
How i should implement the function that will receive as argument the tree in which i want to insert nodes?
You could always return a pointer to the root, like this
node* insert(node* root, int key) {
node *p, *q;
p = (node*) calloc(1,sizeof(node));
p->key = key;
if (root == NULL) {
root = p;
return root;
}
q = root;
for (;;) {
if (key < q->key) {
if (q->left == 0) {
q->left = p;
return root;
} else q = q->left;
} else if (key > q->key) {
if (q->right == 0) {
q->right = p;
return root;
} else q = q->right;
} else {
free(p);
return root;
}
}
}
And you create your tree like -
node* root1 = NULL;
root1 = insert(root1,3)

Generalized Linked List: Adding Child Link whenever an opening bracket occurs

Here is my code for generating a GLL for the string input: a,(b,c),d where (b,c) will be linked as a child at the next link of a.
GLL* generateList(char poly[])
{
GLL* newNode = NULL, *first = NULL, *ptr = NULL;
while (poly[i] != '\0')
{
if (poly[i] == ')')
{
return first;
}
else
{
if (poly[i] != ',')
{
if (poly[i] != '(')
{
newNode = createNode(poly[i], 0);
}
else
{
++i;
newNode = createNode('#', 1);
newNode->dlink = generateList(poly);
}
}
}
if (first != NULL)
{
ptr = first;
while (ptr->next != NULL)
{
ptr = ptr->next;
}
ptr->next = newNode;
}
else
{
first = newNode;
}
i++;
}
return first;
}
And here is the structure I used for each node.
typedef struct gll
{
int tag;
struct gll* next;
char data;
struct gll* dlink;
} GLL;
I am not finding a way to add that child link to the parent link whenever the bracket opens. The programs runs in a loop.
Note: I have declared i=0 as a global variable to hold the position of character.
Edit: Here is the createNode function
GLL* createNode(char value, int flag)
{
GLL* newNode;
newNode = (GLL *) malloc(sizeof(GLL)*1);
newNode->data = value;
newNode->dlink = NULL;
newNode->tag = flag;
newNode->next = NULL;
return newNode;
}
How do I do it then?
You could do something like that:
#include <stdbool.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct gll
{
int tag;
struct gll* next;
char data;
struct gll* dlink;
} GLL;
GLL* createNode(char value, int flag)
{
GLL* newNode = calloc(1, sizeof(*newNode));
if (!newNode)
return NULL;
newNode->tag = flag;
newNode->data = value;
return newNode;
}
void freeList(GLL *list)
{
for (GLL *current_node = list, *temp; current_node; current_node = temp) {
temp = current_node->next;
freeList(current_node->dlink);
free(current_node);
}
}
GLL* generateList(char *poly, size_t *pos)
{
size_t const length = strlen(poly);
GLL *head = NULL;
GLL *tail = NULL;
for (; *pos < length; ++*pos) {
if (poly[*pos] == '(') {
++*pos; // don't have the next called generateList() read '(' again
tail->dlink = generateList(poly, pos);
if (!tail->dlink) {
freeList(head);
return NULL;
}
continue;
}
else if (poly[*pos] == ')') {
return head;
}
else if (isalpha((char unsigned)poly[*pos])) {
if (!head) {
head = tail = createNode(poly[*pos], 0);
}
else {
tail->next = createNode(poly[*pos], 0);
tail = tail->next;
}
continue;
}
else if (poly[*pos] == ',')
continue;
fputs("Format error :(\n\n", stderr);
freeList(head);
return NULL;
}
return head;
}
void printList(GLL *list)
{
for (GLL *node = list; node; node = node->next) {
printf("%c ", node->data);
if (node->dlink) {
putchar('(');
printList(node->dlink);
printf("\b) ");
}
}
}
int main(void)
{
size_t pos = 0;
GLL *list = generateList("a,(b,(c,d,e(f)),g,h),i,j,k", &pos);
printList(list);
putchar('\n');
freeList(list);
}
Output
a (b (c d e (f)) g h) i j k
Also, if flag is true then it means that the data is not to be considered but there is a child list to be linked.
Sorry, but I don't get how there could be a child list if there is no data for the node.

Binary Search tree, node deletion crash

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?

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