Building BFS with an implemented queue in C - c

I'm implementing a graph traversal breadth-first search that I found here. However, their implementation involves integers and without any linked list. I was playing around with it a little bit I have no luck in getting any results because it doesn't seem to work as intended.
This is the code that I currently have:
(main.c)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
typedef struct s_list
{
struct s_list *next;
void *content;
} t_list;
typedef struct s_queue
{
t_list *first;
t_list *last;
} t_queue;
typedef struct s_node
{
struct s_node *next;
int vertex;
} t_node;
typedef struct s_graph
{
t_node **adj_lists;
int *visited;
int total_vertices;
} t_graph;
/*Graph functions*/
t_node *create_node(int vertex);
t_graph *create_graph(int vertices);
void add_edge(t_graph *graph, int src, int dst);
void bfs(t_graph *graph, int start_vertex);
/*Misc functions*/
void my_putstr(char *str);
void *my_memalloc(size_t size);
void *my_memset(void *ptr, int value, size_t num);
void my_bzero(void *s, size_t n);
/*Queue functions*/
t_queue *init_queue(void);
void enqueue(t_queue *queue, void *content);
void *dequeue(t_queue *queue);
void *peek_queue(t_queue *queue);
int is_empty(t_queue *queue);
void my_print_queue(t_queue *queue);
t_node *create_node(int val)
{
t_node *new_node;
new_node = (t_node*)my_memalloc(sizeof(t_node));
new_node->vertex = val;
new_node->next = NULL;
return (new_node);
}
t_graph *create_graph(int vertices)
{
int i;
t_graph *graph;
i = 0;
graph = my_memalloc(sizeof(t_graph));
graph->total_vertices = vertices;
printf("graph->total_vertices: %d\n", vertices);
graph->adj_lists = (t_node**)my_memalloc(sizeof(t_node));
graph->visited = my_memalloc(sizeof(int) * vertices);
while (i < vertices)
{
graph->adj_lists[i] = NULL;
graph->visited[i] = 0;
i++;
}
return (graph);
}
void add_edge(t_graph *graph, int src, int dst)
{
t_node *new_node;
new_node = create_node(dst);
new_node->next = graph->adj_lists[src];
graph->adj_lists[src] = new_node;
new_node = create_node(src);
new_node->next = graph->adj_lists[dst];
graph->adj_lists[dst] = new_node;
}
void bfs(t_graph *graph, int start_vertex)
{
t_queue *queue;
queue = init_queue();
graph->visited[start_vertex] = 1;
printf("start_vertex before enqueue %d\n", start_vertex);
my_print_queue(queue);
enqueue(queue, &start_vertex);
printf("start_vertex after enqueue %d\n", start_vertex);
while (!is_empty(queue))
{
my_print_queue(queue);
int current_vertex;
t_node *tmp;
current_vertex = (int)dequeue(queue);
printf("Visited %d nodes\n", current_vertex);
tmp = graph->adj_lists[current_vertex];
while (tmp)
{
int adj_vertex;
adj_vertex = tmp->vertex;
if (graph->visited[adj_vertex] == 0)
{
graph->visited[adj_vertex] = 1;
printf("%d\n", graph->visited[adj_vertex]);
enqueue(queue, &adj_vertex);
my_print_queue(queue);
}
tmp = tmp->next;
}
}
}
t_queue *init_queue(void)
{
t_queue *node;
node = (t_queue *)my_memalloc(sizeof(t_queue));
node->first = NULL;
node->last = NULL;
return (node);
}
void enqueue(t_queue *queue, void *content)
{
t_list *node;
node = (t_list *)my_memalloc(sizeof(t_list));
node->content = content;
node->next = NULL;
if (!queue->last)
{
queue->last = node;
queue->first = node;
}
else
{
queue->last->next = node;
queue->last = queue->last->next;
}
return ;
}
void *dequeue(t_queue *queue)
{
t_list *tmp;
tmp = queue->first;
if (!tmp)
return (NULL);
else
{
queue->first = tmp->next;
return (tmp->content);
}
}
void *peek_queue(t_queue *queue)
{
if (queue->first == NULL)
return (NULL);
return (queue->first->content);
}
int is_empty(t_queue *queue)
{
return (queue->first == NULL);
}
void my_print_queue(t_queue *queue)
{
if (is_empty(queue))
my_putstr("Empty queue\n");
else
{
while (!is_empty(queue))
{
int val = *(int *)queue->first->content;
printf("%d \n", val);
dequeue(queue);
}
}
}
void my_putstr(char *str)
{
int i;
i = 0;
while (str[i])
write(1, &str[i++], 1);
}
void *my_memalloc(size_t size)
{
char *str;
str = ((void*)malloc(size));
if (!str)
return (NULL);
my_bzero(str, size);
return (str);
}
void *my_memset(void *ptr, int value, size_t num)
{
unsigned char *uptr;
uptr = (unsigned char*)ptr;
while (num--)
*uptr++ = (unsigned char)value;
return (ptr);
}
void my_bzero(void *s, size_t n)
{
my_memset(s, 0, n);
}
int main(void)
{
t_graph *graph;
graph = create_graph(3);
add_edge(graph, 0, 1);
add_edge(graph, 0, 2);
add_edge(graph, 2, 4);
bfs(graph, 2);
return (0);
}
I did some research like type-casting a void pointer to make it into a char or int, or any other data type. What happens is that the create graph does it's creation after calling it; but, when it comes to the bfs, it doesn't show the correct output after. It never prints the visited vertices. I'm getting a result of
graph->total_vertices: 3
start_vertex before enqueue 2
Empty queue
start_vertex after enqueue 2
2
Visited 0 nodes
The expected output should be something like this:
Queue contains
0 Resetting queueVisited 0
Queue contains
2 1 Visited 2
Queue contains
1 4 Visited 1
Queue contains
4 Resetting queueVisited 4
I've been trying to figure out by myself to the point that I'm burning out. What am I doing wrong in here?
While posting this, I will keep debugging on my side and see what it does with a couple print statements.

I can point out the following mistakes:
my_print_queue destroys your queue. So anything after it's call works with empty queue.
You don't fill visited with to zeroes. By default their values is pretty much arbitrary. Since you compare their values with 0, it makes sense that comparison fails.

Related

C - Separate Chaining Hash Table - Output and Space Issues

so basically I wrote a program to initialize, insert, and output the whole hash table. I thought I did pretty good, but there's many issues.
First issue being, some names are displayed with an additional weird character, why??
Second issue being, I can only input a size parameter (for initialize(size) function) of <8. Anything above 7 will output "Out of Space!" but why?? I thought I managed the space pretty well from what I was taught at uni:((
Please help!
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct list_node *node_ptr;
struct list_node
{
node_ptr next;
char *key;
char *value;
};
typedef node_ptr LIST;
typedef node_ptr position;
struct hash_table
{
LIST *list_ptr_arr;
unsigned int table_size;
};
typedef struct hash_table *HASHTABLE;
unsigned long long int
hash(const char *key, unsigned int hash_size)
{
unsigned long long int hash;
for(int i = 0; key[i]; i++)
{
hash = (hash<<32)+key[i];
}
return (hash%hash_size);
}
unsigned int
next_prime(int number)
{
int j;
for(int i = number; ; i++)
{
for(j = 2; j<i; j++)
{
if(i%j == 0){break;}
}
if(i==j){return j;}
}
}
HASHTABLE
initialize(unsigned int table_size)
{
HASHTABLE H;
H = (HASHTABLE) malloc(sizeof(struct hash_table));
if(H==NULL){printf("Out of Space!"); return 0;}
H->table_size = next_prime(table_size);
H->list_ptr_arr = (position*) malloc(sizeof(LIST)*H->table_size);
if(H->list_ptr_arr==NULL){printf("Out of Space!"); return 0;}
H->list_ptr_arr = (LIST*) malloc(sizeof(struct list_node)*H->table_size);
for(unsigned int i = 0; i<H->table_size; i++)
{
if(H->list_ptr_arr[i]==NULL){printf("Out of Space!"); return 0;}
H->list_ptr_arr[i]=NULL;
}
return H;
}
position
set(const char *key, const char *value)
{
position entry = (position) malloc(sizeof(struct list_node));
entry->value = (char*) malloc(strlen(value)+1);
entry->key = (char*) malloc(strlen(key)+1);
strncpy(entry->key,key,strlen(key));
strncpy(entry->value,value,strlen(value));
entry->next = NULL;
return entry;
}
void
insert(const char *key, const char *value, HASHTABLE H)
{
unsigned int slot = hash(key, H->table_size);
node_ptr entry = H->list_ptr_arr[slot];
node_ptr prev;
if(entry==NULL)
{
H->list_ptr_arr[slot] = set(key, value);
return;
}
while(entry!=NULL)
{
if(strcmp(entry->key, key)==0)
{
free(entry->value);
entry->value = malloc(strlen(value)+1);
strncpy(entry->value,value,strlen(value));
return;
}
prev = entry;
entry = prev->next;
}
prev->next = set(key, value);
}
void
dump(HASHTABLE H)
{
for(unsigned int i = 0; i<H->table_size; i++)
{
position entry = H->list_ptr_arr[i];
if(H->list_ptr_arr[i]==NULL){continue;}
printf("slot[%d]: ", i);
for(;;)
{
printf("%s|%s -> ", entry->key, entry->value);
if(entry->next == NULL)
{
printf("NULL");
break;
}
entry = entry->next;
}
printf("\n");
}
}
int main()
{
HASHTABLE H = initialize(7);
insert("name1", "David", H);
insert("name2", "Lara", H);
insert("name3", "Slavka", H);
insert("name4", "Ivo", H);
insert("name5", "Radka", H);
insert("name6", "Kvetka", H);
dump(H);
return 0;
}
Then I tried to change it up a bit:
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct list_node *node_ptr;
struct list_node
{
node_ptr next;
char *key;
char *value;
};
typedef node_ptr LIST;
typedef node_ptr position;
struct hash_table
{
LIST *list_ptr_arr;
unsigned int table_size;
};
typedef struct hash_table *HASHTABLE;
unsigned long long int
hash(const char *key, unsigned int hash_size)
{
unsigned long long int hash;
for(int i = 0; key[i]; i++)
{
hash = (hash<<32)+key[i];
}
return (hash%hash_size);
}
unsigned int
next_prime(int number)
{
int j;
for(int i = number; ; i++)
{
for(j = 2; j<i; j++)
{
if(i%j == 0){break;}
}
if(i==j){return j;}
}
}
HASHTABLE
initialize(unsigned int table_size)
{
HASHTABLE H;
H = (HASHTABLE) malloc(sizeof(struct hash_table));
if(H==NULL){printf("Out of Space!1"); return 0;}
H->table_size = next_prime(table_size);
H->list_ptr_arr = (position*) malloc(sizeof(LIST)*H->table_size);
if(H->list_ptr_arr==NULL){printf("Out of Space!2"); return 0;}
H->list_ptr_arr = (LIST*) malloc(sizeof(struct list_node)*H->table_size);
for(unsigned int i = 0; i<H->table_size; ++i)
{
if(H->list_ptr_arr[i]==NULL){printf("Out of Space!3"); return 0;}
H->list_ptr_arr[i]->value="HEAD";
H->list_ptr_arr[i]->next=NULL;
}
return H;
}
void
insert(const char *key, const char *value, HASHTABLE H)
{
unsigned int slot = hash(key, H->table_size);
LIST entry = H->list_ptr_arr[slot], newNode;
newNode = (position) malloc(sizeof(struct list_node));
if(newNode==NULL){printf("Out of Space4!"); return;}
newNode->next = entry->next;
strncpy(newNode->key,key,strlen(key));
strncpy(newNode->value,value,strlen(value));
entry->next = newNode;
}
void
dump(HASHTABLE H)
{
for(unsigned int i = 0; i<H->table_size; i++)
{
position entry = H->list_ptr_arr[i];
position p = entry->next;
if(p==NULL){continue;}
printf("slot[%d]: ", i);
for(;;)
{
printf("%s|%s -> ", p->key, p->value);
if(p->next == NULL)
{
printf("NULL");
break;
}
p = p->next;
}
printf("\n");
}
}
int main()
{
HASHTABLE H = initialize(4);
insert("name1", "David", H);
insert("name2", "Lara", H);
insert("name3", "Slavka", H);
insert("name4", "Ivo", H);
insert("name5", "Radka", H);
insert("name6", "Kvetka", H);
dump(H);
return 0;
}
Thank you!
I modified the second piece of code, it runs correctly on my computer.
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SIZE 256
// typedefing struct list_node multiple times is confusing, so I remove these typedefs
struct list_node {
struct list_node *next;
// strings need storage space in the memory,
// declaring key and value as array here can save some calls to malloc()
char key[MAX_SIZE];
char value[MAX_SIZE];
};
struct hash_table {
struct list_node **list_ptr_arr;
unsigned int table_size;
};
// it's better not to hide pointer type using typedef
typedef struct hash_table HASHTABLE;
unsigned long long int hash(const char *key, unsigned int hash_size) {
// hash is not initialized originally (the value is choosed randomly)
unsigned long long int hash = 5;
for (int i = 0; key[i]; i++) {
hash = (hash << 32) + key[i];
}
return (hash%hash_size);
}
unsigned int next_prime(int number) {
int j;
for (int i = number; ; i++) {
for (j = 2; j < i; j++) {
if (i%j == 0) { break; }
}
if (i == j) { return j; }
}
}
HASHTABLE *initialize(unsigned int table_size) {
HASHTABLE *H;
// you don't need to type cast malloc() result in C
H = malloc(sizeof(*H));
H->table_size = next_prime(table_size);
// I suppose list_ptr_arr is a pointer to an array of struct list_node * object
H->list_ptr_arr = malloc(sizeof(*(H->list_ptr_arr)) * H->table_size);
for (unsigned int i = 0; i < H->table_size; ++i) {
// malloc() for H->list_ptr_arr only allocated area for struct list_node * array, the struct list_node pointed to is not allocated yet, so malloc() here
H->list_ptr_arr[i] = malloc(sizeof(*(H->list_ptr_arr[i])));
strcpy(H->list_ptr_arr[i]->value, "HEAD");
H->list_ptr_arr[i]->next = NULL;
}
return H;
}
void insert(const char *key, const char *value, HASHTABLE *H) {
unsigned int slot = hash(key, H->table_size);
struct list_node *entry = H->list_ptr_arr[slot], *newNode;
newNode = malloc(sizeof(*newNode));
newNode->next = entry->next;
// strlen() doesn't count the '\0', just use strcpy here
strcpy(newNode->key, key);
strcpy(newNode->value, value);
entry->next = newNode;
}
void dump(HASHTABLE *H) {
for (unsigned int i = 0; i < H->table_size; i++) {
struct list_node *entry = H->list_ptr_arr[i];
struct list_node *p = entry->next;
if (p == NULL) { continue; }
printf("slot[%d]: ", i);
for (;;) {
printf("%s|%s -> ", p->key, p->value);
if (p->next == NULL) {
printf("NULL");
break;
}
p = p->next;
}
printf("\n");
}
}
int main() {
HASHTABLE *H = initialize(4);
insert("name1", "David", H);
insert("name2", "Lara", H);
insert("name3", "Slavka", H);
insert("name4", "Ivo", H);
insert("name5", "Radka", H);
insert("name6", "Kvetka", H);
dump(H);
return 0;
}
P.S. Don't forget to free the hashtable.

Generric search function at generic link list

I have generic link list in C that know how to push struct to list.
The problem is the I can't implement generic search in those link list:
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
struct Node
{
void *data;
struct Node *next;
};
void push(struct Node** head_ref, void *new_data, size_t data_size)
{
struct Node* new_node = (struct Node*)malloc(sizeof(struct Node));
new_node->data = malloc(data_size);
new_node->next = (*head_ref);
int i;
for (i=0; i<data_size; i++)
*(char *)(new_node->data + i) = *(char *)(new_data + i);
(*head_ref) = new_node;
}
struct A
{
int a1;
long a2;
};
struct B
{
long b1;
int b2;
};
void find_a1_in_a_list (int desire_a1 , struct Node *a_list)
{
struct A *a;
while(NULL != a_list)
{
a = (struct A*) a_list->data;
if(a->a1 == desire_a1)
printf("found!\n");
a_list = a_list->next;
}
}
void find_b1_in_b_list (long desire_b1 , struct Node *b_list)
{
struct B *b;
while(NULL != b_list)
{
b = (struct B*) b_list->data;
if(b->b1 == desire_b1)
printf("found!\n");
b_list = b_list->next;
}
}
void find_generic (void* desire_value,int off,struct Node *list)
{
while(NULL != list)
{
void* check_value_void = list->data + off;
int check_value_cast = *(int *) check_value_void; //How to know if cast to int or long ?????
if(check_value_cast == *(int *)desire_value) //How to know if cast to int or long ?????
printf("found generic!\n");
list = list->next;
}
}
void main()
{
struct Node *a_list = NULL;
struct A a;
a.a1=1;
a.a2=2;
push(&a_list, &a, sizeof(struct A));
find_a1_in_a_list(1,a_list);
struct Node *b_list = NULL;
struct B b;
b.b1=1;
b.b2=2;
push(&b_list, &b, sizeof(struct B));
find_b1_in_b_list(1,b_list);
//tried to make it generic
int search = 3;
find_generic(&search,offsetof(struct A, a2),a_list);
}
As you can I tried to makes generic search in function find_generic by passing the offset to the value in struct, that code works but only for int
but how can I pass to this generic function if I want to search int or long ,so I will know how to makes cast ?
Is there any way to cast void * by size so I can pass sizeof(int) or sizeof(long) and makes the casting by this value? or maybe another way?
Passing the compare function directly instead of playing with offsetof/sizeof will be more flexible:
struct Node *find_generic (struct Node *list,
int (*fn_cmp)(void const *a, void const *b),
void const *data)
{
while (list) {
if (fn_cmp(list->data, data) == 0)
break;
list = list->next;
}
return list;
}
and then create custom compare functions
static int cmp_A(void const *a_, void const *b_)
{
struct A const *a = a_;
struct A const *b = b_;
if (a->a1 == b->a1 && a->a2 == b->a2)
return 0;
return 1;
}
and call it like
struct A key = {
.a1 = 23,
.a2 = 42,
};
find_generic(a_list, cmp_A, &key);

Error: Syntax error before 'struct'

My code is basically functions used for making/using a stack. I've tried almost everything, but I don't know why my program is displaying this error:
Error: Syntax error before 'struct'
#include "stack.h"
#include <stdio.h>
#include <stdlib.h>
#define CAPACITY 128
struct stack_struct {
ElemType items[CAPACITY];
int top;
};
StackPtr stk_create(){
StackPtr s = malloc(sizeof(struct stack_struct));
s->top = -1; // stack initially empty
return s;
}
// TODO
StackPtr stk_clone(StackPtr s) {
return NULL; // temporary placeholder
}
void stk_free(StackPtr s) {
free(s);
}
int stk_push(StackPtr s, ElemType val){
if(s->top == CAPACITY - 1)
struct stack_struct * temp;
temp = (struct stack_struct*)malloc(sizeof(struct stack_struct));
s->top++;
s->items[s->top] = val;
return 1;
}
ElemType stk_pop(StackPtr s){
if(s->top == -1)
abort(); // library function which terminates program!!!
s->top--;
return s->items[s->top+1];
}
int stk_is_full(StackPtr s){
return s->top == CAPACITY-1;
}
int stk_is_empty(StackPtr s){
return s->top == -1;
}
int stk_size(StackPtr s) {
return s->top+1;
}
void stk_clear(StackPtr s){
s->top = -1;
}
void stk_print(StackPtr s) {
int i;
printf("\n----TOP-----\n");
for(i=s->top; i>=0; i--) {
printf(FORMAT_STRING, s->items[i]);
}
printf("---BOTTOM---\n");
}
int main() {
StackPtr sptr;
sptr = stk_create();
stk_push(sptr, 1.7);
stk_push(sptr, 3.14);
stk_print(sptr);
stk_pop(sptr);
stk_print(sptr);
stk_free(sptr);
}
As I could see, function stack_push should look like this
int stk_push(StackPtr s, ElemType val){
if(stk_is_full(s))
return -1; // stack already full, we couldn't push new elem
s->top++;
s->items[s->top] = val;
return 1;
}
I think error in this line (line 35 in your source code):
struct stack_struct * temp;
. Let's try
typedef struct stack_struct * temp;
or change declare struct
struct stack_struct {
ElemType items[CAPACITY];
int top;} stack;
and then call
stack* temp;
in line 35.

SegFault when passing functions in C

I'm getting a SegFault when passing a function pointer through a couple of structs and I can't figure out what I'm doing wrong. Here's the code:
typedef int (*CompareFuncT)( void *, void * );
typedef void (*DestructFuncT)( void * );
struct AVL
{
void * obj;
struct AVL * parent;
struct AVL * leftChild;
struct AVL * rightChild;
};
typedef struct AVL * AVLPtr;
struct SortedList
{
AVLPtr root;
CompareFuncT comp;
DestructFuncT dest;
};
typedef struct SortedList * SortedListPtr;
SortedListPtr SLCreate(CompareFuncT cf, DestructFuncT df){
SortedListPtr slp = malloc(sizeof(struct SortedList));
if(slp == NULL){
printf("Not enough space for list\n");
return NULL;
}
slp->root = NULL;
slp->comp = cf;
slp->dest = df;
return slp;
}
AVLPtr avl_insert(AVLPtr root, AVLPtr parent, void * obj, int (*compare)( void *, void * )){
int s = 5;
int k = 6;
compare(&s, &k);
if(root == NULL){
root = malloc(sizeof(struct AVL));
if(root == NULL){
printf ("Out of memory - creating AVL node\n");
return NULL;
}
root->obj = obj;
root->parent = parent;
root->leftChild = NULL;
root->rightChild = NULL;
return root;
}
else if (compare(obj, root->obj) < 0){
root->leftChild = avl_insert(root->leftChild, root, obj, compare);
root = balance(root);
}
else if (compare(obj, root->obj) >= 0){
root->rightChild = avl_insert(root->rightChild, root, obj, compare);
root = balance(root);
}
return root;
}
int SLInsert(SortedListPtr list, void * newObj){
list->root = avl_insert(list->root, newObj, list->comp);
if(list->root == NULL)
return 0;
return 1;
}
int compareInts(void *p1, void *p2)
{
int i1 = *(int*)p1;
int i2 = *(int*)p2;
return i1 - i2;
}
void destroyBasicTypeNoAlloc(void *p) {
return;
}
int main(int argc, char **argv) {
int s = 9;
SortedListPtr list = SLCreate(compareInts, destroyBasicTypeNoAlloc);
SLInsert(list, &s);
return 0;
}
There's obviously more parameters going through the function, but this is the propagation of my compare function. I'm getting a SegFault on the compare in avl_insert. I have a feeling I'm just not passing a pointer where I should be, but I just can't find it.
The error is your call of malloc:
SortedListPtr slp = malloc(sizeof(SortedListPtr));
You are allocating the number of bytes that a pointer takes up, which is incorrect. It should be:
SortedListPtr slp = malloc(sizeof(struct SortedList));

pointers and values

I have written the following code, and it prints the root value correctly, but not the ret value. Here a memory address is potentially printed (1707388). I believe that ret could now be modified and the result would be seen in main. Any help is appreciated.
#include <stdlib.h>
struct node{
int value;
int order;
struct node *left;
struct node *right;
};
typedef struct node node_t;
node_t array[10];
void createTree(node_t *p, int order){
p->value = rand()%10;
p->order = order;
printf("%i", p->value);
printf(" ");
printf("%i\n", p->order);
if (!order){
p->left = NULL;
p->right = NULL;
return;
}
order--;
createTree(&p->left, order);
createTree(&p->right, order);
}
void traverse(node_t *current, node_t *ret, int size){
printf("%i\n", current->value);
if (current->value > size){
ret = current;
traverse(&current->left, &ret, size);
traverse(&current->right, &ret, size);
}
return;
}
int main(void){
node_t *root = &array[0];
node_t *ret;
srand(time(NULL));
createTree(root, 4);
int i = 3;
printf("%s", "root-value: ");
printf("%i\n", root->value);
traverse(root, ret, i);
printf("%s", "root-value: ");
printf("%i\n", root->value);
printf("%i\n", ret->value);
return 1;
}
This:
void createTree(node_t *p, int order)
Should be
void createTree(node_t **p, int order)
Otherwise you are modifying a local node_t pointer, instead of the one outside the function. Your tree isn't being built properly either.
You are passing ret by value to
void traverse(node_t *current, node_t *ret, int size){
When the function changes ret, the changes do not propagate back to the caller.
This means that ret in main() remains uninitialized, and the behaviour of your code is undefined.
To fix this, make traverse either return ret, or take it as node_t**.
There are few issues with the code.
First, you don't correctly allocate the memory for nodes. In your code, you are passing wrong pointer type, futhermore, pointer to uninitialized area.
Here, how it can be used differently:
node_t *createTree(int order)
{
node_t *result = malloc(sizeof(*result));
result->value = rand() % 10;
result->order = order;
if (order)
{
result->left = createTree(order - 1);
result->right = createTree(order - 1);
}
else
{
result->left = result->right = 0;
}
return result;
}
Then, your traverse function need some block to restrict agains failed search:
node_t *traverse(node_t *current, int size)
{
node_t *ret = NULL;
if (current->value > size)
{
// assuming current node fit - stops the search
ret = current;
}
if (!ret && current->left)
{
// try left node
ret = traverse(current->left, size);
}
if (!ret && current->right)
{
// try right node
ret = traverse(current->right, size);
}
return ret;
}
In case you need (usually you do), here is a destroyTree:
void destroyTree(node_t *node)
{
if (!node) return; // we treat NULL as a valid pointer for simplicity
destroyTree(node->left);
destroyTree(node->right);
free(node);
}
And here is a usage example:
node_t *root, *found;
root = createTree(4);
found = traverse(root, 3);
if (found)
{
printf("Found!");
}
destroyTree(root);
In traverse(node_t *current, node_t *ret, int size), ret is a stack variable. In other words, you are passing the pointer by value, instead of passing it by reference.
What have you done at the moment is essentially the same as:
int f(int i) {
...
i = <any value>;
...
}
In this case you are modifying only a copy of the value.
In your program, you are also modifying a copy of the pointer. Outside of the function the pointer stays not modified.
If you want to modify it, you need to pass a pointer to it:
void traverse(node_t *current, node_t **ret, int size){
...
*ret = current;
...
return;
}
The same for createTree().

Resources