Searching for a string in BST fails - c

I am searching a string in a BST. If I found the string, I just return it. If not found, I print 3 suggestions:
the last traversed node before declaring that the node is not found
the inorder successsor
the inorder predecessor
My code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
void line() {
printf("\n-------------------------\n");
}
typedef struct node node;
struct node {
node* left, *right;
char *key;
};
node *newnode(char* key) {
node *n = malloc(sizeof(node));
n->key = malloc(strlen(key) + 1);
strcpy(n->key, key);
n->right = n->left = NULL;
return n;
}
node *insirtNode(node *root, char *key) {
if (!root) return newnode(key);
if (strcmp(key, root->key) < 0) {
root->left = insirtNode(root->left, key);
} else if (strcmp(key, root->key) > 0) {
root->right = insirtNode(root->right, key);
}
return root;
}
node* search(node *root, char *key, node **pred, node **succ, node **last) {
if (root) {
//printf("%s:%s=%d.\n",root->key,key,strcasecmp(key,root->key));
if (strcasecmp(key, root->key) == 0) {
printf("%s - is correct", root->key);
line();
return root;
}
if (strcasecmp(key, root->key) < 0) {
if (!root->left) {
*last = root;
}
*succ = root;
return search(root->left, key, pred, succ, last);
} else {
if (!root->right) {
*last = root;
}
*pred = root;
return search(root->right, key, pred, succ, last);
}
} else return NULL;
}
int main() {
char input[60];
printf("enter a word:\n");
gets(input);
line();
node *pred = NULL, *succ = NULL, *temp = NULL, *last = NULL;
node *root = NULL;
root = insirtNode(root, "anas");
root = insirtNode(root, "anad");
root = insirtNode(root, "anay");
root = insirtNode(root, "anaz");
temp = search(root, input, &pred, &succ, &last);
if (!temp) {
printf("%s incorrect, suggestions: %s %s %s", input, succ->key, pred->key, last->key);
}
printf("\n");
return 0;
}
The functions sometimes work when the string
exist in the BST. If not, it returns garbage without printing anything.

There are these issues:
in the main function where succ->key, pred->key and last->key are accessed when any of these pointers could still be NULL.
Not a problem, but last is likely to be equal to either succ or pred, so probably you want to avoid printing the same key twice.
Suggested correction:
if (temp == NULL) {
printf("%s incorrect, suggestion(s):", input);
if (pred != NULL) printf(" %s", pred->key);
if (succ != NULL) printf(" %s", succ->key);
if (last != NULL && last != pred && last != succ) printf(" %s", last->key);
}
The call to malloc assumes that a char is a byte. This is wrong. So multiply the number of characters by sizeof(char):
n->key = malloc((strlen(key) + 1) * sizeof(char));

Related

delete the biggest number in linked list from anywhere (in C)

I have this code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node
{
int x;
struct Node *next;
} Node;
void deallocate(Node **root)
{
Node *curr = *root;
while (curr != NULL)
{
Node *aux = curr;
curr = curr->next;
free(aux);
}
*root = NULL;
}
void insert_end(Node **root, int value)
{
Node *new_node = malloc(sizeof(Node));
if (new_node == NULL)
{
exit(1);
}
new_node->next = NULL;
new_node->x = value;
if (*root == NULL)
{
*root = new_node;
return;
}
Node *curr = *root;
while (curr->next != NULL)
{
curr = curr->next;
}
curr->next = new_node;
}
void deserialize(Node **root)
{
FILE *file = fopen("duom.txt", "r");
if (file == NULL)
{
exit(2);
}
int val;
while (fscanf(file, "%d, ", &val) > 0)
{
insert_end(root, val);
}
fclose(file);
}
int largestElement(struct Node *root)
{
int max = INT_MIN;
while (root != NULL)
{
if (max < root->x)
max = root->x;
root = root->next;
}
return max;
}
void deleteN(Node **head, int position)
{
Node *temp;
Node *prev;
temp = *head;
prev = *head;
for (int i = 0; i < position; i++)
{
if (i == 0 && position == 1)
{
*head = (*head)->next;
free(temp);
}
else
{
if (i == position - 1 && temp)
{
prev->next = temp->next;
free(temp);
}
else
{
prev = temp;
// Position was greater than
// number of nodes in the list
if (prev == NULL)
break;
temp = temp->next;
}
}
}
}
int main()
{
Node *root = NULL;
printf("MENU:\n");
printf("if you press 0 the list will be created \n");
printf("if you press 1 the list will be printed on a screen\n");
printf("if you press 2 it deletes the biggest element\n");
printf("if you press 3 the program ends\n\n");
int meniu;
printf("press:\n");
scanf("%d", &meniu);
while (meniu != 3)
{
if (meniu == 0)
{
deserialize(&root);
printf("sarasas sukurtas.\n");
}
if (meniu == 1)
{
for (Node *curr = root; curr != NULL; curr = curr->next)
printf("%d\n", curr->x);
}
if (meniu == 2)
{
int max_element = largestElement(root);
printf("%d max\n", max_element);
deleteN(&root, max_element);
}
printf("press:\n");
scanf("%d", &meniu);
}
deallocate(&root);
return 0;
}
When I compile and run the delete function it only deletes the biggest number first time and if I call it second time it deletes the last number of the list. Can someone help me fix that?
I edited it so all of the code can be seen because it was hard to understand it like I had it before
Your largestElement returns the largest data value in the list.
However, here:
int max_element = largestElement(root);
printf("%d max\n",max_element);
deleteN(&root, max_element);
you use the return value as if it is the position of the node with the largest element.
Instead of largestElement you need a function that returns the position of the element with the largest data value.
It would look something like:
int positionOfLargestElement(struct Node* root)
{
int pos = 0;
int maxpos = 0;
int max = INT_MIN;
while (root != NULL) {
++pos;
if (max < root->x)
{
max = root->x;
maxpos = pos;
}
root = root->next;
}
return maxpos;
}
note: The exact code depends a bit on whether the first node is considered to be position 0 or position 1 but the principle is the same.

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.

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.

How to delete nodes in a doubly linked list

I'm having trouble deleting nodes in a doubly linked list, the program crash and i can't figure out the problem. Can you please help me?
This is the full code that creates new nodes, views them and deletes them.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Test
{
int id;
};
typedef struct Node {
struct Test structure;
struct Node * next;
struct Node *prev;
}TNode;
typedef TNode* Node;
void NewNode(struct Test p, Node *pp)
{
Node temp;
temp = (Node)malloc(sizeof(struct Node));
temp->structure = p;
temp->next = *pp;
temp->prev = NULL;
if(*pp != NULL)
{
(*pp)->prev = temp;
}
*pp = temp;
}
void ReadStructure(struct Test * p)
{
printf("\nID:");
scanf(" %d", &p->id);
}
void ViewList(Node node)
{
Node temp;
while(node != NULL)
{
temp = node->prev;
if(node->prev == NULL)
{
printf("Prev = NULL\n");
}
else
{
printf("Prev: %d\n", temp->structure.id);
}
printf("Curr: %d\n", node->structure.id);
node = node->next;
}
}
void Delete(Node * head, Node del)
{
if(*head == NULL || del == NULL)
{
return;
}
if(*head == del)
{
*head = del->next;
}
if(del->next != NULL)
{
del->next->prev = del->prev;
}
if(del->prev != NULL)
{
del->prev->next = del->next;
}
free(del);
return;
}
int Menu()
{
int c;
printf("*** M E N U ***\n"
"1 - New Node\n"
"2 - View List\n"
"3 - Delete\n"
"0 - Exit\n"
"\n>> ");
scanf(" %d", &c);
return c;
}
int main()
{
int c;
struct Test test;
Node list = NULL;
Node del = NULL;
do {
c = Menu();
switch (c)
{
case 1: ReadStructure(&test);
NewNode(test, &list); break;
case 2: ViewList(list); break;
case 3: printf("\nElement to Delete: ");
scanf("%d", &del->structure.id);
Delete(&list, del); break;
default: c = 0;
}
} while (c != 0);
return 0;
}
I think the problem is related to the scanf() for the Node del, but i'm not sure. When i just pass list or list->next as second argument to the function Delete() it works. Is everything all right with the code?
int main()
{
...
Node del = NULL;
...
scanf("%d", &del->structure.id);
Your program should crash here. You are dereferencing a null pointer.
Probably you will need to read the user input into a temporary id variable, then search the list for a matching item, and if you find one, then you can try deleting it.
Ok, i added a function that searches for the node to be deleted and i modified a bit the Delete() function, this is the workaround, thank you for the suggestions:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Test
{
int id;
};
typedef struct Node {
struct Test structure;
struct Node * next;
struct Node *prev;
}TNode;
typedef TNode* Node;
void NewNode(struct Test p, Node *pp)
{
Node temp;
temp = (Node)malloc(sizeof(struct Node));
temp->structure = p;
temp->next = *pp;
temp->prev = NULL;
if(*pp != NULL)
{
(*pp)->prev = temp;
}
*pp = temp;
}
void ReadStructure(struct Test * p)
{
printf("\nID:");
scanf(" %d", &p->id);
}
void ViewList(Node node)
{
Node temp;
while(node != NULL)
{
temp = node->prev;
if(node->prev == NULL)
{
printf("Prev = NULL\n");
}
else
{
printf("Prev: %d\n", temp->structure.id);
}
printf("Curr: %d\n", node->structure.id);
node = node->next;
}
}
Node SearchNode(Node head)
{
int d;
printf("\nElement to Delete:");
scanf("%d", &d);
while(head != NULL)
{
if(head->structure.id == d)
{
return head;
}
head = head->next;
}
printf("\nNo Element [%d] Found", d);
return NULL;
}
void Delete(Node * head, struct Test temp)
{
Node del = SearchNode(*head);
if(*head == NULL || del == NULL)
{
return;
}
if(*head == del)
{
*head = del->next;
}
if(del->next != NULL)
{
del->next->prev = del->prev;
}
if(del->prev != NULL)
{
del->prev->next = del->next;
}
free(del);
return;
}
int Menu()
{
int c;
printf("\n*** M E N U ***\n"
"1 - New Node\n"
"2 - View List\n"
"3 - Delete\n"
"0 - Exit\n"
"\n>> ");
scanf(" %d", &c);
return c;
}
int main()
{
int c;
struct Test test, del;
Node list = NULL;
do {
c = Menu();
switch (c)
{
case 1: ReadStructure(&test);
NewNode(test, &list); break;
case 2: ViewList(list); break;
case 3: Delete(&list, del); break;
default: c = 0;
}
} while (c != 0);
return 0;
}
del value is NULL, but you reference it when you delete.
What you need is to search a node in the list for the givent id and then delete it.

BST build tree double pointers

I am unsure how to set a pointer to a pointer to build a tree. Like once I have traveled to a leaf and call insert, how should I insert another element calling insert with the root node or the address of the root pointer? I think the problem with this function is the name root where that should be the double pointer right?
#include "bst.h"
#include <stdio.h>
#include <stdlib.h>
//arbitrary list of temp nodes
TreeNode *new_node, *root, *tmp, *parent;
int elemArray[100], i1, i2, i0;
int main( int argc, char *argv[] ) {
//Throw error is *Argv[] is not an integer
//assuming it was an integer
int cnt = atoi( argv[1] );
printf( "number is %d\n", cnt );
//
printf("Enter %i integer values to place in tree:\n", cnt);
for ( i1 = 0; i1 < cnt; ++i1) {
scanf( "%d", &elemArray[i1] );
}
//first ouput "INput Values"
printf( " Input Values:\n " );
for ( i2 = 0; i2 < cnt; ++i2) {
printf( "%d\n", elemArray[i2] );
}
TreeNode** root = (TreeNode*)malloc(sizeof(TreeNode*));
buildTree(root, elemArray, cnt );
printf( "Preorder:\n ");
//traverse
//TreeNode* tempN = malloc(sizeof(TreeNode*));
//tempN->data= 5;
traverse( root, PREORDER);
//traverse a single node
printf( "Inorder:\n ");
printf( "Postorder:\n ");
//Build tree with each element
return 0;
}
This is the .h file
/// The definition of the tree structure
typedef struct TreeNode {
int data ; // the data stored in the node
struct TreeNode* left ; // node's left child
struct TreeNode* right ; // node's right child
} TreeNode;
/// The three supported traversals
typedef enum {
PREORDER, // parent -> left -> right
INORDER, // left -> parent -> right
POSTORDER // left -> right -> parent
} TraversalType;
and lastly the traverse function so far as it failed the first test.
void traverse( const TreeNode* root, const TraversalType type ) {
if ( type == PREORDER) {
if (root != NULL)
{
printf("%d", root->data);
traverse( root->left, PREORDER);
traverse( root-> right, PREORDER);
}
}
}
void build_tree(TreeNode** root, const int elements[], const int count) {
TreeNode* node = malloc(sizeof(TreeNode*));
node->left = node ->right = NULL;
*root = node;
for ( int i0 = 0; i0 < count; ++i0 ){
TreeNode* node = malloc(sizeof(TreeNode*));
*root = node;
node->data = elements[cnt];
insertNode( &(*root), &node );
}
}
Why is the insertNode getting the errors (multiple) and I don't know which is the pointer and which is the struct. GUYS ANY HINT WILL BE HELPFUL PLEASE?
bst.c:94:20: error: request for member 'left' in something not a structure or union
insert(root->left, new_node);
void insertNode(TreeNode** root, TreeNode* new_node) {
if (new_node-> data < &root-> data) {
if (&root-> left == NULL)
&root-> left == new_node;
else
insert(root->left, new_node);
}
if (new_node->data > &root->data) {
if(&root-> right ==NULL)
&root->right = new_node;
else
insert(&root->right, new_node);
}
}
SO for Edit 2: I do have a header file which has a build_Tree(**root, elems[], sizeofElem[]), which means i need a helper function insert. Yes is would be easier to add by input starting*.
Edit 1
#include "bst.h"
#include <stdio.h>
#include <stdlib.h>
//arbitrary list of temp nodes
TreeNode *new_node, *root, *tmp, *parent, *current;
int elemArray[5], i1, i2, i0;
/*
Insert a new node into the tree by referencing the root and using recursion
*/
TreeNode* getN(int dataElem) {
TreeNode *newNode = malloc(sizeof(*newNode));
if (newNode != NULL)
{
newNode->data = dataElem;
newNode->left = NULL;
newNode->right = NULL;
}
return newNode;
}
/** This func should just be the root of the tree in the parameter,
but I like the idea of a pointer becuase it helps to create a tempory
pointer rather than newNode
**/
TreeNode* addNodeToTree(TreeNode *root, int data) {
TreeNode *current = *root; //define the current pointer to the root always
TreeNode *parent = *root
TreeNode *newNode = getN(data);
if (*root == NULL)
{
printf("First Node");
*root = newNode;
}
else
{
while(current != NULL)
{
parent = current;
if (current->data > data)
current = current->left;
else if (current->data < data)
current = current->right;
}
if (parent->data > data)
parent->left = newNode;
else if (parent->data < data)
parent->right = newNode;
}
}
void build_Tree(TreeNode** root, const int elements[], const int count) {
*root = malloc(sizeof(TreeNode));
for ( i0 = 0; i0 < count; ++i0 ){
printf("%d\n", elements[count]);
addNodeToTree(&root, elements[count]);
}
}
int main( int argc, char *argv[] ) {
//Throw error is *Argv[] is not an integer
//assuming it was an integer
int cnt = atoi( argv[1] );
printf( "number is %d\n", cnt );
//
printf("Enter %i integer values to place in tree:\n", cnt);
for ( i1 = 0; i1 < cnt; ++i1) {
scanf( "%d", &elemArray[i1] );
}
//first ouput "INput Values"
printf( " Input Values:\n " );
for ( i2 = 0; i2 < cnt; ++i2) {
printf( "%d\n", elemArray[i2] );
printf("building tree0\n");
}
printf("building tree\n");
TreeNode** root = (TreeNode**)malloc(sizeof(TreeNode*));
TreeNode *root = NULL;
build_Tree(root, elemArray, cnt );
printf( "Preorder:\n ");
//traverse
//TreeNode* tempN = malloc(sizeof(TreeNode*));
//tempN->data= 5;
traverse( *root, PREORDER); //pass the pointer of root to traverse the tree
//traverse a single node
printf( "Inorder:\n ");
printf( "Postorder:\n ");
//Build tree with each element
return 0;
}
void traverse( const TreeNode* root, const TraversalType type ) {
if ( type == PREORDER) {
if (root != NULL)
{
printf("%d", root->data);
traverse( root->left, PREORDER);
traverse( root-> right, PREORDER);
}
}
}
/**
void insertNode(TreeNode** root, TreeNode* new_node) {
if (new_node-> data < *root-> data) {
if (*root-> left == NULL)
*root-> left == new_node;
else
insert(*root->left, new_node);
}
if (new_node->data > *root->data) {
if(*root-> right ==NULL)
*root->right = new_node;
else
insert(*root->right, new_node);
}
}
**/
//question1: what is the
Edit 2 for main and build_tree
void build_Tree(TreeNode** root, const int elements[], const int count) {
//*root = malloc(sizeof(TreeNode));
for ( i0 = 0; i0 < count; i0++ ){
//create the node
//
TreeNode *current = *root; //define the current pointer to the root always
TreeNode *parent = *root;
//dont create node
int data = elements[i0];
TreeNode *newNode = getN(data);
if (*root == NULL)
{
printf("First Node %d\n", elements[i0]);
*root = newNode;
}
else
{
printf("Next Node %d\n", elements[i0]);
while(current != NULL)
{
parent = current;
if (current->data > data)
current = current->left;
else if (current->data < data)
current = current->right;
}
if (parent->data > data)
parent->left = newNode;
else if (parent->data < data)
parent->right = newNode;
}
//return root;
}
}
TreeNode* getN(int dataElem) {
TreeNode *newNode = malloc(sizeof(*newNode));
if (newNode != NULL)
{
newNode->data = dataElem;
newNode->left = NULL;
newNode->right = NULL;
}
return newNode;
}
int main( int argc, char *argv[] ) {
//Throw error is *Argv[] is not an integer
//assuming it was an integer
int cnt = atoi( argv[1] );
printf( "number is %d\n", cnt );
//
printf("Enter %i integer values to place in tree:\n", cnt);
for ( i1 = 0; i1 < cnt; ++i1) {
scanf( "%d", &elemArray[i1] );
}
//first ouput "INput Values"
printf( " Input Values:\n " );
for ( i2 = 0; i2 < cnt; ++i2) {
printf( "%d\n", elemArray[i2] );
printf("building tree0\n");
}
printf("building tree\n");
TreeNode* root; //= malloc(sizeof(TreeNode*));
root = NULL;
build_Tree(&root, elemArray, cnt );
printf( "Preorder:\n ");
//traverse
//TreeNode* tempN = malloc(sizeof(TreeNode*));
//tempN->data= 5;
//traverse( *root, PREORDER); //pass the pointer of root to traverse the tree
//traverse a single node
printf( "Inorder:\n ");
printf( "Postorder:\n ");
//Build tree with each element
return 0;
}
Say you created a function addNodeToTree(TreeNode *root, int data), pass the root node, and data to it as argument.
Now inside this function, simply create another variable say TreeNode *current = root which will help us basically to traverse the tree and place the node at its respective position, and TreeNode *newNode = NULL(this will become the new node, which is to be inserted).
Now before moving ahead, to actually place the node, we will first check, if the root is not null, i.e. the tree is EMPTY. For that, we will test:
if (root == NULL)
{
newNode = malloc(sizeof(*newNode)); // else we can make a function for this
// thingy too. Creating a function too,
// for you to look at.
root = newNode;
}
If the tree is not EMPTY, i.e. it contains a node already, then we will traverse the tree to find the place, where to put the new node. So the else part, will be like:
else
{
parent = current = root;
// This loop will actually help us, find the `parent`,
// of the `newNode`(which is to be inserted)
while (current != NULL)
{
parent = current;
if (current->data > data)
current = current->left;
else if (current->data < data)
current = current->right;
}
// Now once, we have found, the node, under which the
// newNode will be placed, now we have to check, whether
// newNode will become a `left child/right child` of the
// parent.
newNode = getNewNode(data);
if (parent->data > data)
parent->left = newNode;
else if (parent->data < data)
parent->right = newNode;
return root;
}
TreeNode * getNewNode(int data)
{
TreeNode *newNode = malloc(sizeof(*newNode));
if (newNode != NULL)
{
newNode->data = data;
newNode->left = NULL;
newNode->right = NULL;
}
return newNode;
}
Now the newNode has been inserted, and you can simply traverse in any order to see the Tree.
EDIT 1:
Here is one working example, just see if this makes sense. Else please do ask any question, that might may arise.
#include <stdio.h>
#include <stdlib.h>
typedef struct TREENODE
{
int data;
struct TREENODE *left;
struct TREENODE *right;
}TreeNode;
void display(TreeNode *node)
{
printf("*********************************\n");
printf("Address of Node: %p\n", node);
printf("Data: %d\n", node->data);
printf("Left Child: %p\n", node->left);
printf("Right Child: %p\n", node->right);
printf("*********************************\n");
}
TreeNode * getNewNode(int data)
{
TreeNode *newNode = malloc(sizeof(*newNode));
if (newNode != NULL)
{
newNode->data = data;
newNode->left = NULL;
newNode->right = NULL;
}
return newNode;
}
int getIntData(char *message)
{
int value = 0;
char buffer[BUFSIZ] = {'\0'};
fputs(message, stdout);
fgets(buffer, sizeof(buffer), stdin);
sscanf(buffer, "%d", &value);
return value;
}
TreeNode * addNodeToTree(TreeNode *root, int data)
{
TreeNode *current = root, *parent = root;
TreeNode *newNode = getNewNode(data);
if (root == NULL)
{
root = newNode;
}
else
{
while(current != NULL)
{
parent = current;
if (current->data > data)
current = current->left;
else if (current->data < data)
current = current->right;
}
if (parent->data > data)
parent->left = newNode;
else if (parent->data < data)
parent->right = newNode;
}
return root;
}
void inOrderTraversal(TreeNode *root)
{
if (root != NULL)
{
inOrderTraversal(root->left);
display(root);
inOrderTraversal(root->right);
}
}
int main(void)
{
TreeNode *root = NULL;
int data = 0;
data = getIntData("Enter Data: ");
root = addNodeToTree(root, data);
data = getIntData("Enter Data: ");
root = addNodeToTree(root, data);
data = getIntData("Enter Data: ");
root = addNodeToTree(root, data);
inOrderTraversal(root);
return EXIT_SUCCESS;
}
EDIT 2:
To make addNodeToTree(...), implement pointer to a pointer, one simply needs to change the function as:
void addNodeToTree(TreeNode **root, int data)
{
TreeNode *current = *root;
TreeNode *parent = *root;
TreeNode *newNode = getNewNode(data);
if (*root == NULL)
{
*root = newNode;
}
else
{
// same as before, just don't return anythingy, from the function.
// As the function uses pointer to a pointer, hence whatever changes
// are done, here will be reciprocated in the main function automatically
}
// no need to return anythingy
}
And the call from main will now look like:
int main(void)
{
TreeNode *root = NULL;
int data = 0;
data = getIntData("Enter Data: ");
addNodeToTree(&root, data);
// Just see the call to addNodeToTree(...), the rest is same, as before
}
EDIT 3:
In order to take elements from an array instead of adding them directly to tree, just change the main method to this form:
int main(void)
{
TreeNode *root = NULL;
int element[5] = {19, 11, 5, 28, 25};
int size = sizeof(element) / sizeof(element[0]);
int counter = 0;
for (counter = 0; counter < size; ++counter)
{
addNodeToTree(&root, element[counter]);
}
inOrderTraversal(root);
return EXIT_SUCCESS;
}

Resources