Need help creating maxHeap function - c

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct listNode {
int id;
struct listNode *next;
} ListNode;
typedef struct treeNode {
char *word;
char *key;
int freq;
ListNode *head;
struct treeNode *left;
struct treeNode *right;
} TreeNode;
TreeNode *insertItem(TreeNode *root, char *gword);
void printTreeInorder(TreeNode *v);
void searchforexist(TreeNode *root, char *key);
int searchItem(TreeNode *root, char *word);
void Heap(TreeNode *arr[],TreeNode *root, int i);
void maxheap(TreeNode *arr[],int k);
void freeNodes(TreeNode *root);
#define MAX 25
int main() {
char in[MAX];
char word[MAX];
TreeNode *root = NULL;
int comp;
int f=0;
int t=0;
FILE *fp = fopen("input.txt", "r");
memset(word, 0, MAX);
if (fp != NULL) {
while (fscanf(fp, "%24s \n", word) != EOF) {
root = insertItem(root, word);//insert items
t++;
if (strcmp(word, "eof") == 0) break;
}
fclose(fp);
}
// User inputs word
printf("Give word");
printf("\n");
scanf("%s",in);
comp=strcmp(in,"#");
while(comp!=0)
{
printf("Give word");
printf("\n");
scanf("%s",in);
comp=strcmp(in,"#");
if(comp==1)
break;
f=searchItem(root,in);
printf("%d",f);
f=0;
printf("\n");
}
TreeNode *arr[t];
Heap(arr,root,t);// HEAPPPPPPPPPPPPPPPPPPPPPPPPPPPP
printTreeInorder(root);
printf("\n");
freeNodes(root);
return 0;
}
TreeNode *insertItem(TreeNode *root, char *gword) {
TreeNode *v = root;
TreeNode *pv = NULL;
while (v != NULL) {
pv = v;
int comp = strcmp(gword, v->word);
if (comp < 0) {
v = v->left;
} else if (comp > 0) {
v = v->right;
} else {
char *word = v->word;
searchforexist(root,v->word);
return root;
}
}
TreeNode *tmp = (TreeNode *)malloc(sizeof(TreeNode));
tmp->word = strdup(gword);
tmp->left = tmp->right = NULL;
tmp->freq = 1;
if (root != NULL) {
if (strcmp(gword, pv->word) < 0) {
pv->left = tmp;
} else {
pv->right = tmp;
}
} else
root = tmp;
return root;
}
void searchforexist(TreeNode *root, char *word) {
if(root == NULL) {
return;
}
int comp = strcmp(word, root->word);
if(comp == 0) {
root->freq++;
} else {
searchforexist(comp < 0 ? root->left : root->right , word);
}
}
int searchItem(TreeNode *root, char *word)
{
if(root == NULL) {
return 0;
}
int comp = strcmp(word, root->word);
if(comp == 0) {
return root->freq;
} else {
searchItem(comp < 0 ? root->left : root->right , word);
}
}
void Heap(TreeNode *arr[],TreeNode *root, int i)
{
int k=0;
while(k<i)
{
if(root==NULL){
maxheap(arr,k);
}
arr[k]=root;
k++;
if (k=i){
maxheap(arr,k);
break;
}
Heap(arr,root->left,k);
Heap(arr,root->right,k);
}
}
void maxheap(TreeNode *arr[],int k)
{
int i;
int j;
for (i = 0; i < k; i++)
{
for (j = 0; j < k; j++)
{
if(arr[i]->freq>arr[j]->freq)
{
TreeNode *tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
}
for (i = 0; i < k; i++)
{
printf("%s %d",arr[i]->word,arr[i]->freq);
}
}
void printTreeInorder(TreeNode *v)
{
if (v==NULL) return;
printf("(");
printTreeInorder(v->left);
printf(")");
printf(" %.4s ", v->word);
printf("(");
printTreeInorder(v->right);
printf(")");
}
void freeNodes(TreeNode *root) {
if (root == NULL) {
return;
}
freeNodes(root->left);
freeNodes(root->right);
if(root->word != NULL) free(root->word);
if(root->key != NULL) free(root->key);
free(root);
return;
}
This program reads a file and puts all strings to a binary search tree. Repeating words are not added but the frequency counter increases (searchforexist). Then the user types a word and the program displays the frequency of the word typed.
The above works fine using any input file.
However im having trouble with the next steps of the assignment:
After that the hole tree is suppose to be copied in a maxheap based on the frequency of each word. The heap must be created using array with size equal to the elements of a tree. Every cell of said array must contain a pointer that points to a node in the binary search tree so we can still access the word inside and its frequency.
The user then inputs an int number and the programm prints all words that have frequency less that the number inputed by the user.
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct listNode {
int id;
struct listNode *next;
} ListNode;
typedef struct treeNode {
char *word;
char *key;
int freq;
ListNode *head;
struct treeNode *left;
struct treeNode *right;
} TreeNode;
TreeNode *insertItem(TreeNode *root, char *gword);
void printTreeInorder(TreeNode *v);
void searchforexist(TreeNode *root, char *key);
int searchItem(TreeNode *root, char *word);
void freeNodes(TreeNode *root);
#define MAX 25
int main() {
char in[MAX];
char word[MAX];
TreeNode *root = NULL;
int comp;
int f=0;
FILE *fp = fopen("input.txt", "r");
memset(word, 0, MAX);
if (fp != NULL) {
while (fscanf(fp, "%24s \n", word) != EOF) {
root = insertItem(root, word);//insert items
if (strcmp(word, "eof") == 0) break;
}
fclose(fp);
}
// User inputs word
printf("Give word");
printf("\n");
scanf("%s",in);
comp=strcmp(in,"#");
while(comp!=0)
{
printf("Give word");
printf("\n");
scanf("%s",in);
comp=strcmp(in,"#");
if(comp==1)
break;
f=searchItem(root,in);
printf("%d",f);
f=0;
printf("\n");
}
//heapcreating here
printTreeInorder(root);
printf("\n");
freeNodes(root);
return 0;
}
TreeNode *insertItem(TreeNode *root, char *gword) {
TreeNode *v = root;
TreeNode *pv = NULL;
while (v != NULL) {
pv = v;
int comp = strcmp(gword, v->word);
if (comp < 0) {
v = v->left;
} else if (comp > 0) {
v = v->right;
} else {
char *word = v->word;
searchforexist(root,v->word);
return root;
}
}
TreeNode *tmp = (TreeNode *)malloc(sizeof(TreeNode));
tmp->word = strdup(gword);
tmp->left = tmp->right = NULL;
tmp->freq = 1;
if (root != NULL) {
if (strcmp(gword, pv->word) < 0) {
pv->left = tmp;
} else {
pv->right = tmp;
}
} else
root = tmp;
return root;
}
void searchforexist(TreeNode *root, char *word) {
if(root == NULL) {
return;
}
int comp = strcmp(word, root->word);
if(comp == 0) {
root->freq++;
} else {
searchforexist(comp < 0 ? root->left : root->right , word);
}
}
int searchItem(TreeNode *root, char *word)
{
if(root == NULL) {
return 0;
}
int comp = strcmp(word, root->word);
if(comp == 0) {
return root->freq;
} else {
searchItem(comp < 0 ? root->left : root->right , word);
}
}
void printTreeInorder(TreeNode *v)
{
if (v==NULL) return;
printf("(");
printTreeInorder(v->left);
printf(")");
printf(" %.4s ", v->word);
printf("(");
printTreeInorder(v->right);
printf(")");
}
void freeNodes(TreeNode *root) {
if (root == NULL) {
return;
}
freeNodes(root->left);
freeNodes(root->right);
if(root->word != NULL) free(root->word);
if(root->key != NULL) free(root->key);
free(root);
return;
}

I and many of us make simple mistakes. Use the automated tools you have to increase your coding efficiency.
Save time, enable all compiler warnings - or use a better compiler.
warning: control reaches end of non-void function [-Wreturn-type]
searchItem() needs to return a value.
int searchItem(TreeNode *root, char *word) {
if (root == NULL) {
return 0;
}
int comp = strcmp(word, root->word);
if (comp == 0) {
return root->freq;
} else {
// searchItem(comp < 0 ? root->left : root->right, word);
return searchItem(comp < 0 ? root->left : root->right, word);
}
}
Other problems may exist.

Related

Variable value changing after returning to the loop

I've been coding for a C - Binary Search Tree, but the Program always change variable when returning to the loop. I've tried debugging it and checked every pointer but found no errors.
There is a simple run(bold for input, italic for notes)
a
Please enter name of pet:
aaa //pet name, input
Please enter pet kind:
bbb //pet kind, input
add pet success
aaa //pet name, is correct
//pet kind, return to 0
q
0b //pet name, turn to 0b
//pet kind, always 0
Bye.
The code is the next:
main.c
#include "tree.h"
#define CHECK
char menu(void);
void addpet(Tree *pt);
char *s_gets(char *st, int n);
int main(void)
{
Tree pets;
char choice;
InitializeTree(&pets);
while ((choice = menu()) != 'q')
{
switch (choice)
{
case 'a':
addpet(&pets);
#ifdef CHECK
printf("%s", pets.root->head->petname);
printf("%s", pets.root->head->petkind); // petkind back to 0
#endif
break;
default:
puts("Switching error");
}
}
#ifdef CHECK
puts(pets.root->head->petname); // trun to '\000' '372' '\333' 'b' '\376' '\177'
puts(pets.root->head->petkind); // always 0
#endif
puts("Bye.");
return 0;
}
char menu(void)
{
int ch;
ch = getchar();
while (getchar() != '\n')
continue;
return ch;
}
void addpet(Tree *pt)
{
Item temp;
if (TreeIsFull(pt))
puts("No room in the club!");
else
{
puts("Please enter name of pet:");
s_gets(temp.petname, SLEN);
puts("Please enter pet kind:");
s_gets(temp.petkind, SLEN);
temp.next = NULL;
if (AddItem(&temp, pt))
puts("add pet success");
}
}
char *s_gets(char *st, int n)
{
char *ret_val;
char *find;
ret_val = fgets(st, n, stdin);
if (ret_val)
{
find = strchr(st, '\n');
if (find)
*find = '\0';
else
while (getchar() != '\n')
continue;
}
return ret_val;
}
tree.c
#include "tree.h"
static Node *MakeNode(Item *pi);
static bool ToLeftNode(const Node *i1, const Node *i2);
static bool ToRightNode(const Node *i1, const Node *i2);
static void AddNode(Node *new_node, Node *root);
static PairNode SeekNode(const Node *pn, const Tree *ptree);
static PairItem SeekList(Node *, const Item *);
void InitializeTree(Tree *ptree)
{
ptree->root = NULL;
ptree->size = 0;
}
bool TreeIsFull(const Tree *ptree)
{
if (ptree->size == MAXITEMS)
return true;
else
return false;
}
bool AddItem(Item *pi, Tree *ptree)
{
Node *new_node;
PairNode seek_node;
PairItem seek_list;
if (TreeIsFull(ptree))
{
fprintf(stderr, "Tree is full\n");
return false;
}
new_node = MakeNode(pi);
if (new_node == NULL)
{
fprintf(stderr, "Couldn't create node\n");
return false;
}
if ((seek_node = SeekNode(new_node, ptree)).child != NULL)
{
if ((seek_list = SeekList(seek_node.child, pi)).child != NULL)
{
fprintf(stderr, "Attempted to add duplicate item\n");
return false;
}
seek_list.child = pi;
ptree->size++;
return true;
}
ptree->size++;
if (ptree->root == NULL)
ptree->root = new_node;
else
AddNode(new_node, ptree->root);
return true;
}
static void AddNode(Node *new_node, Node *root)
{
if (ToLeftNode(new_node, root))
{
if (root->left == NULL)
root->left = new_node;
else
AddNode(new_node, root->left);
}
else if (ToRightNode(new_node, root))
{
if (root->right == NULL)
root->right = new_node;
else
AddNode(new_node, root->right);
}
else
{
fprintf(stderr, "location error in AddNode()\n");
exit(1);
}
}
static bool ToLeftNode(const Node *i1, const Node *i2)
{
if (strcmp(i1->petname, i2->petname) < 0)
return true;
else
return false;
}
static bool ToRightNode(const Node *i1, const Node *i2)
{
if (strcmp(i1->petname, i2->petname) > 0)
return true;
else
return false;
}
static Node *MakeNode(Item *pi)
{
Node *new_node;
new_node = (Node *)malloc(sizeof(Node));
if (new_node != NULL)
{
strcpy(new_node->petname, pi->petname);
new_node->head = pi;
new_node->left = NULL;
new_node->right = NULL;
}
return new_node;
}
static PairNode SeekNode(const Node *pn, const Tree *ptree)
{
PairNode look;
look.parent = NULL;
look.child = ptree->root;
if (look.child == NULL)
return look;
while (look.child != NULL)
{
if (ToLeftNode(pn, look.child))
{
look.parent = look.child;
look.child = look.child->left;
}
else if (ToRightNode(pn, look.child))
{
look.parent = look.child;
look.child = look.child->right;
}
else
break;
}
return look;
}
static PairItem SeekList(Node *pn, const Item *pi)
{
PairItem seek;
seek.child = pn->head;
seek.parent = NULL;
while (seek.child != NULL)
{
if (strcmp(seek.child->petname, pi->petname) == 0 &&
strcmp(seek.child->petkind, pi->petkind) == 0)
break;
seek.parent = seek.child;
seek.child = seek.child->next;
}
return seek;
}
tree.h
#ifndef TREE_H_
#define TREE_H_
#define SLEN 20
#define MAXITEMS 10
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct item{ char petname[SLEN]; char petkind[SLEN]; struct item *next;} Item;
typedef struct node{ char petname[SLEN]; Item *head; struct node *left; struct node *right;} Node;
typedef struct tree{ Node *root; int size;} Tree;
typedef struct pairnode{ Node *parent; Node *child;} PairNode;
typedef struct pairitem{ Item *parent; Item *child;} PairItem;
void InitializeTree(Tree *ptree);
bool AddItem(Item *pi, Tree *ptree);
#endif
My question was answered elsewhere.
Modify function addpet:
void addpet(Tree* pt)
{
Item* temp = (Item*)malloc(sizeof(Item));
puts("Please enter name of pet:");
s_gets(temp->petname, SLEN);
puts("Please enter pet kind:");
s_gets(temp->petkind, SLEN);
temp->next = NULL;
if (AddItem(temp, pt))
puts("add pet success");
}

Problem searching in my Binary Search Tree

Problem is function bin_search. it works steady on function insert. However, it gets frozen on function search. I think if it's fine on insert, it should be fine on search, but it isn't. Here is my code...
"bst.h":
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node {
int key;
void *data;
struct Node *left, *right;
void (*destroy)(void *data);
} node;
typedef struct Tree {
node *head;
char name;
} tree;
#define key(node) node->key
#define data(node) node->data
#define left(node) node->left
#define right(node) node->right
#define destroy(node) node->destroy
#define tree_head(tree) tree->head
"functions.c":
#include "bst.h"
int bin_search(node *curr, int key, int cnt, node **found) {
cnt++; printf("cnt+\n");
if (curr == NULL) {
return -1;
} else if (curr->key == key) {
printf("curr_key = key\n"); return cnt;
}
if (curr->key < key) {
printf("curr_key < key\n");
if (curr->right == NULL) {
*found = curr;
return -(cnt + 1);
}
return bin_search(curr->right, key, cnt, found);
} else {
printf("curr_key > key\n");
if (curr->left == NULL) {
*found = curr;
return -(cnt + 1);
}
return bin_search(curr->left, key, cnt, found);
}
}
int insert(tree *root, int key, void *data, void (*destroy)(void *data)) {
if (root->head == NULL) {
node* new_node = (node *)malloc(sizeof(node));
left(new_node) = NULL; right(new_node) = NULL; destroy(new_node) = destroy; key(new_node) = key; data(new_node) = data;
tree_head(root) = new_node;
printf("created first node\n"); return 1;
}
int cnt; node **found;
if ((cnt = bin_search(root->head, key, 0, found)) < 0) {
node* new_node = (node *)malloc(sizeof(node));
left(new_node) = NULL; right(new_node) = NULL; destroy(new_node) = destroy; key(new_node) = key; data(new_node) = data;
if ((*found)->key < key) {
(*found)->right = new_node;
} else {
(*found)->left = new_node;
}
printf("created a node at %d\n", -cnt); return 1;
} else {
printf("already exists in tree"); return -1;
}
}
int search(tree *root, int key, void **data) {
if (root->head == NULL) {
printf("tree is empty\n"); return -1;
}
int cnt; node **found;
if ((cnt = bin_search(root->head, key, 0, found)) < 0) {
return -1;
} else {
if ((*found)->key < key) {
*data = (*found)->right->data;
} else {
*data = (*found)->left->data;
}
return cnt;
}
}
"main.c":
#include "bst.h"
#define MAX_NUM 8
#define MAX_LEGNTH 200
int main() {
// create a tree
tree root; root.head = NULL; root.name = 'a';
FILE *inpt = fopen("list.txt", "r"); char buffer[MAX_LEGNTH];
int count = 0;
while (fgets(buffer, MAX_LEGNTH, inpt) != NULL) {
printf("adding: %d\n", atoi(buffer)); insert(&root, atoi(buffer), buffer, NULL);
count++;
}
fclose(inpt);
int result; void **found;
result = search(&root, 2, found); printf("%d\n", result); // problem in here!!
return 0;
}
what is the problem with my 'search' function. I can't find it.
Besides the utterly non-standard use of sizeof(void), you are not providing a correct out-parameter to search. The point of the found argument is to receive the node pointer if the prospect key was discovered. This...
int cnt;
node **found; // <== LOOK HERE
if ((cnt = bin_search(root->head, key, 0, found)) < 0) {
is not the way to do that. It should be done like this:
int cnt;
node *found = NULL;
if ((cnt = bin_search(root->head, key, 0, &found)) < 0) {
// ^^^^^^
and all references to found thereafter should be through found->, not (*found)->
This mistake is made in three different places in your code. The last one is semi-broken, but still broken nonetheless.
void **found = (void *)malloc(sizeof(void));
int result = search(&root, 2, found);
printf("%d\n", result);
That should use this:
void *found = NULL;
int result = search(&root, 2, &found);
printf("%d\n", result);
Whether the rest of your code is broken I cannot say, and frankly we're not in the business of being an online-debugger. Use your local debugger tools; that's what they're for. But the items listed above are definitely a problem.

Circular Doubly Linked List- Delete node

I am working on building circular doubly linked list code.
In my code, there are four function- add node, delete node, print clockwise, print counterclockwise. All my code works fine, besides the delete function. The if(recycle->name == x) line seems not working properly, and free(recycle) also doesn't successfully free the recycle node.
My original code are. as follows
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define nameLen 20
struct Node
{
char name[nameLen];
struct Node *left; //next
struct Node *right; //previous
};
struct Node* current;
struct Node* head;
int count = 0;
struct Node* GetNewNode(char *x)
{
struct Node* newNode;
newNode = (struct Node*)malloc(sizeof(struct Node));
strncpy(newNode->name, x, nameLen);
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
void add_name(char *x)
{
struct Node* temp = current;
struct Node* newNode = GetNewNode(x);
count++;
if(current == NULL)
{
current = newNode;
head = current;
}
else
{
current->left = newNode;
newNode->right = temp;
current = newNode;
current->left = head;
head->right = current;
}
printf("Add %s into database.\n\n", current->name);
}
void delete_name(char *x)
{
int i, j;
struct Node* recycle = current;
if(current == NULL)
{
printf("No data input.");
}
else
{
for (i = 0; i < count; i++)
{
if(recycle->name == x)
{
free(recycle);
j++;
printf("Delete %s from database.\n", x);
}
recycle = recycle->left;
}
if(j == 0)
{
printf("There is no %s in data", x);
}
current = recycle;
}
}
void print_clock(int number)
{
int i;
struct Node* temp = current;
if(temp == NULL)
{
printf("No data input.");
}
else
{
printf("Clockwise: \n");
for(i = 0; i < number; i++)
{
printf("%s ",temp->name);
temp = temp->left;
}
}
printf("\n\n");
}
void print_counter(int number)
{
int i;
struct Node* temp = current;
if(temp == NULL)
{
printf("No data input.");
}
else
{
printf("Counterclockwise: \n");
for(i = 0; i < number; i++)
{
printf("%s ",temp->name);
temp = temp->right;
}
}
printf("\n\n");
}
int main()
{
char s1;
char s2[nameLen];
char name[nameLen];
int number;
while(1)
{
printf("Enter the instruction: ");
scanf("%s %s", &s1, s2);
if (s1 == '+' && sscanf(s2, "%d", &number) == 1)
{
printf("Print out %d name(s) clockwise.\n", number);
print_clock(number);
}
else if (s1 == '-' && sscanf(s2, "%d", &number) == 1)
{
printf("Print out %d name(s) counterclockwise.\n", number);
print_counter(number);
}
else if (s1 == '+' && sscanf(s2, "%s", name) == 1)
{
add_name(s2);
}
else if (s1 == '-' && sscanf(s2, "%s", name) == 1)
{
delete_name(s2);
}
else if (s1 == 'e')
{
printf("Bye.\n");
break;
}
else // No match.
printf("Wrong Input. %s %s\n", &s1, s2);
}
system("pause");
return 0;
}
Statement recycle->name == x checks if two pointers point to the same object in memory. It does not check if two (different) objects in memory have equal content.
Use
if (strcmp(recycle->name, x) == 0) { ...
to check for equal string contents.

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.

Pointers and cstring beginner troubles

I have a problem with the function replace. What I want to accomplish is to replace some special characters, but I haven't written the code yet. So in the replace function we can at this moment just say that the function should print line for line the way I have tried to write. Can someone please correct this function? I can’t really get it
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
struct list_el {
char *ord;
int num;
struct list_el *prev;
struct list_el *next;
};
typedef struct list_el item;
struct list_el *head, *tail; /*Double linked list that makes it easier to add a element to the end of the FIFO list*/
void addNode(struct list_el *curr);
void readFile();
void print();
void replace();
void random();
void len();
int antE = 0;
int randint(int max)
{
int a = (max*rand()/(RAND_MAX+1.0));
return a;
}
int main(int argc, char *argv[]) {
item *curr;
struct list_el *pa;
if(argc == 3) {
readFile();
}
if(argc == 1) {
printf("Too few arguments, must bee 3");
} else if(strcmp(argv[1], "print") == 0) {
print();
} else if(strcmp(argv[1], "random") == 0) {
random();
} else if(strcmp(argv[1], "replace") == 0) {
replace();
} else if(strcmp(argv[1], "remove") == 0) {
printf("Random kommando kalt");
} else if(strcmp(argv[1], "len") == 0) {
len();
} else {
printf("Not a valid command");
}
if(argc == 3) {
free(curr);
}
}
void addNode(struct list_el *curr) {
if(head == NULL) {
head = curr;
curr->prev = NULL;
} else {
tail->next = curr;
curr->prev = tail;
}
tail = curr;
curr->next = NULL;
}
void readFile()
{
FILE *f = fopen("tresmaa.txt", "r");
if(f == 0) {
printf("Could not open file");
exit(8);
}
item *curr;
if(f != NULL) {
int antE = 0;
head = NULL;
char buffer[300];
while(fgets(buffer, 300-1,f) != NULL) {
curr = (item*)malloc(sizeof(item));
curr->ord = malloc(300);
curr->num = antE;
strcpy(curr->ord, buffer);
antE++;
addNode(curr);
}
}
fclose(f);
}
/*Traverserer listen og printer ut linje for lije
*/
void print()
{
item *curr;
printf("Print text:\n");
for(curr = head; curr != NULL; curr = curr->next) {
printf("%s", curr->ord);
}
}
/*Printer ut en tilfeldig setning
*/
void random()
{
item *curr;
int anum = randint(antE);
for(curr = head; curr != NULL; curr = curr->next) {
if(curr->num == anum) {
printf("Print a random line:\n%s", curr->ord);
}
}
}
void replace()
{
item *curr;
int i;
char tmp[300];
printf("Replace vowels ...\n");
printf("... with vowel 'a'\n");
for(curr = head; curr != NULL; curr = curr->next) {
strcpy(tmp, curr->ord);
for(i = 0; i < strlen(tmp); i++) {
printf("%s", tmp[i]);
}
}
}
void len()
{
item *curr;
long nc;
int i;
nc = 0;
for(curr = head; curr != NULL; curr = curr->next) {
nc += strlen(curr->ord);
}
printf("The text is %d characters long", nc);
}
If you just want to print the lines you can do it without the copying and extra loop:
for(curr = head; curr != NULL; curr = curr->next) {
printf("%s\n", curr->ord);
}
Your current code doesn't work because you tell printf with the %s format that its argument will be a string (aka. a pointer to a zero-terminated sequence of characters), but then you give it a single character, not such a pointer.

Resources