Problem searching in my Binary Search Tree - c

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.

Related

Pointer set to NULL but not in debugger

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

Need help creating maxHeap function

#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.

create an array with the values of the nodes at a level

I have to create an array that contains the values of nodes in a level passed as parameter. The function createArray has to return an array containing the values of the nodes at the level passed as parameter. My code is:
#include "stdafx.h"
#include <cstdlib>
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
struct node {
int data;
struct node* left;
struct node* right;
};
struct node* newNode(int data) {
struct node* node = (struct node*)malloc(sizeof(struct node));
node->data = data;
node->left = NULL;
node->right = NULL;
return node;
}
int numNodesLevel(struct node* root, int level) {
if (root == NULL) {
return 0;
}
else {
if (level == 0) {
return 1;
}
return numNodesLevel(root->left, level - 1) + numNodesLevel(root->right, level - 1);
}
}
int max(int a, int b) {
if(a > b) {
return a;
}
else {
return b;
}
}
int height(struct node* root) {
if (root == NULL) {
return -1;
}
else {
if (root->left == NULL && root->right == NULL) {
return 0;
}
return max(height(root->left), height(root->right)) + 1;
}
}
int maxNodesLevel(struct node* root) {
if (root == NULL) {
return 0;
}
else {
int max = 0;
int h = height(root);
int i = 0;
for (i = 0; i <= h; i++) {
if (numNodesLevel(root, i) > max) {
max = numNodesLevel(root, i);
}
}
return max;
}
}
void fill(struct node* root, int* A, int level, int* i) {
if (root != NULL) {
if (level == 0) {
A[*i] = root->data;
*i = *i + 1;
}
fill(root->left, A, level - 1, i);
fill(root->right, A, level - 1, i);
}
}
int* createArray(struct node* root, int level) {
if (root != NULL) {
int *A = (int*)calloc(maxNodesLevel(root), sizeof(int));
int i = 0;
fill(root, A, level, &i);
return A;
}
}
int main(){
struct node* root = newNode(12);
root->left = newNode(3);
root->right = newNode(16);
root->left->left = newNode(2);
root->left->right = newNode(2);
root->right->left = newNode(2);
root->right->right = newNode(22);
printf("%d", createArray(root,1));
getchar();
return 0;
}
The result should be 3,16 which are the values of the nodes at level 1, but it gives me different numbers like 22721648. These numbers are different every time I run the code, so I think there must be something wrong in the way I use pointers, but I can't figure out where is the error.
Can somebody help me?
The code is correct, but only mistake here is createArray() returns an array and you are considering it as int.
Add following code instead of printf() and it will work.
int level = 1, *arr;
arr = createArray(root, level);
for(int i = 0; i < 2 * level; i++){
printf("%d ", arr[i]);
}
Hope it will help !!

Having trouble creating an adjacency list

I am trying to represent a graph using an adjacency list, but I am currently struggling with it. For some reason the edges are getting assigned to the wrong vertexes and I can't figure out why. I step through the code and the first 3 vertex pairs are added just fine but for some reason on the 4th nothing works right and I end up creating multiple new edges and not even the values of them are correct. A sample input is below as well as the C code. Anyone know why this might be happening? Note that
void print_distance(vertex*, int);
int check_an_edge(edge*);
void free_head(vertex*);
have not been implemented but free_head is used to free the entire list
5
(2,3)
(1,4)
(1,3)
(3,4)
(4,5)
#include <stdio.h>
#include <stdlib.h>
#include "input_error.h"
#define VertexToSearch 1
typedef struct node {
int value;
struct node* nextedge;
} edge;
typedef struct node1 {
int vertexnumber;
int distance;
struct node* edge;
} vertex;
vertex* load_file(char*);
void create_vertex_list(vertex*, int);
void create_new_edge(int, int, vertex*);
void print_distance(vertex*, int);
int check_an_edge(edge*);
void free_head(vertex*);
enum error program_error;
int main(int argc, char** argv) {
vertex* array;
array = load_file(argv[1]);
free_head(array);
return 0;
}
vertex* load_file(char* filename) {
int count;
int vertex1;
int vertex2;
FILE* file = fopen(filename, "r");
if (file == NULL) {
printf("%s did not open", filename);
program_error = FILE_FAILED_TO_OPEN;
exit(program_error);
}
fscanf(file, "%d", &count);
vertex* head = malloc(sizeof(vertex)* count);
create_vertex_list(head, count);
for (int i = 0; i < count; i++) {
fscanf(file, "\n(%d,%d)", &vertex1, &vertex2);
create_new_edge(vertex1, vertex2, head);
}
fclose(file);
return head;
}
void create_vertex_list(vertex head[], int count) {
vertex *new_node;
for (int i = 0; i < count; i++) {
new_node = malloc(sizeof (vertex));
new_node->vertexnumber = i + 1;
new_node->edge = NULL;
new_node->distance = -1;
*(head +i)= *new_node;
}
}
void create_new_edge(int vertex1, int vertex2, vertex* head) {
edge* new = malloc(sizeof (edge));
edge* new1 = malloc(sizeof (edge));
new->value = vertex1;
new1->value = vertex2;
new->nextedge = NULL;
new->nextedge = NULL;
if ((head +vertex1 - 1)->edge == NULL) {
(head +vertex1 - 1)->edge = new1;
} else {
edge* temp = (head +vertex1 - 1)->edge;
while (temp != NULL) {
if (temp->nextedge == NULL) {
temp->nextedge = new1;
break;
} else {
temp = temp->nextedge;
}
}
}
if ((head +vertex2 - 1)->edge == NULL) {
(head +vertex2 - 1)->edge = new;
} else {
edge* temp = (head +vertex2 - 1)->edge ;
while (temp != NULL) {
if (temp->nextedge == NULL) {
temp->nextedge = new1;
break;
} else {
temp = temp->nextedge;
}
}
}
}
In your create_new_edge function in the second if-statement you try to add new1. I think it's a copy-paste bug and you should change it to new.
if ((head +vertex2 - 1)->edge == NULL) {
(head +vertex2 - 1)->edge = new;
} else {
edge* temp = (head +vertex2 - 1)->edge ;
while (temp != NULL) {
if (temp->nextedge == NULL) {
temp->nextedge = new1; // Change here new1 to new
break;
} else {
emp = temp->nextedge;
}
}
}

Inserting and Removing from Linked List

This is a hashtable implementation.
I have the insert kinda working but how do I return the linked list?
I know that the remove is not done yet but I understand the concept, my problem is returning the adjusted list.
I tried to make the hashtable a global variable but the programming would force when I ran it.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <assert.h>
#include <string.h>
struct node {
char * data;
struct node * next;
};
struct hashtable {
struct node ** table;
int size;
int nentries;
};
struct hashtable * hashtable_new(int size) {
struct hashtable * result;
result = malloc(sizeof(struct hashtable));
result -> size = size;
result -> nentries = 0;
result -> table = malloc(sizeof(struct node) * size);
int i = 0;
for (i = 0; i < result->size; i++) {
result->table[i] = NULL;
// result->table[i]->data = NULL;
}
return result;
}
unsigned hash_string(struct hashtable *this, char * str) {
unsigned hash = 0;
int i = 0;
for ( i = 0; str[i] != '\0'; i++ ) {
hash = hash * 37 + str[i];
}
//return hash;
return hash % this-> size;
}
void hashtable_free(struct hashtable * this) {
int i;
struct node *table_nodes, *current, *next;
for(i = 0; i<this->size; i++) {
table_nodes = this->table[i];
current = table_nodes;
while (current != NULL){
next = current->next;
free(current);
current = next;
}
this->table[i] = NULL;
}
free(&this->table);
free(&this->size);
free(&this->nentries);
free(this);
}
void hashtable_insert(struct hashtable * table, char * string) {
struct node * new_node;
unsigned index = hash_string(table, string);
if(table->table[index] == NULL) {
printf("\nIndex: %d", index);
new_node = malloc(sizeof(struct node));
new_node -> next = table->table[index];
new_node -> data = string;
printf("\nData: %s", new_node->data);
table -> table[index] = new_node;
table -> nentries++;
printf("\n");
} else {
new_node = malloc(sizeof(struct node));
new_node->data = string;
new_node->next = NULL;
struct node * current = table->table[index];
struct node * next;
int size = 1;
while (current != NULL) {
next = current->next;
//if(current->data == string){
//return;
//}
if(current-> next == NULL){
//last element in list
current->next = new_node;
table->nentries++;
size++;
printf("\nIndex: %d", index);
printf("\nSize: %d", size);
printf("\nData: %s", current->next->data);
printf("\n");
return;
}
current = next;
size++;
}
}
}
void remove_hash(struct hashtable * this, char * item) {
//unsigned index = hash_string(this, item);
}
int lookup(struct hashtable * this, char * item) {
struct node *temp;
unsigned int index = hash_string(this, item);
temp = this->table[index];
while(temp != NULL) {
// do something
printf("%s, ", temp->data);
if(temp->data == item) {
printf("found %s\n", temp->data);
}
temp = temp->next;
}
return 0;
}
void print(struct hashtable * this) {
int i = 0;
printf("\n Size %d \n", this->size);
if(this == NULL) {
printf("Please construct the hashtable");
return;
}
for (i = 0; i < this->size; i++) {
if(this->table[i] == NULL) {
printf("\n %d: <empty>", i);
} else {
printf("\n %d: %s ", i, this->table[i]->data);
if(this->table[i]->next != NULL) {
printf("%s ", this->table[i]->next->data);
}
}
}
}
int main(int argc, char **argv) {
//struct node *theNode;
struct hashtable *theHash;
theHash = hashtable_new(9);
hashtable_insert(theHash, "I");
hashtable_insert(theHash, "am");
hashtable_insert(theHash, "a");;
hashtable_insert(theHash, "fish");
hashtable_insert(theHash, "glub");
print(theHash);
hashtable_insert(theHash, "glub");
lookup(theHash, "I");
print(theHash);
//printf("\n\n\n");
hashtable_free(theHash);
//print(theHash);
return 0;
}
Since C doesn't let you pass by reference, you can try returning the hashtable then reassigning your variable with the result of hashtable_insert:
struct hashtable *hashtable_insert(struct hashtable *table, char *string) {
// awesome code here
return current;
}
And then call it with:
theHash = hashtable_insert(theHash, "Wow!");

Resources