I'm trying to add values to a binary search tree so for that I've written two functions one that create a new node and another which insert these values to the tree
So this is the code
typedef struct Node {
void *data;
struct Node *left;
struct Node *right;
} Node;
Node *createNode(void *data,size_t s){
Node *newNode = (Node *)malloc(s * sizeof(Node));
newNode->data = data;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
void addValueBt(Node ** node, void *data, size_t s,int (* compar)(const void *, const void *)){
if (*node == NULL)
*node = createNode(data,s);
else if (compar((*node)->data,data) > 0)
addValueBt(&(*node)->left, data, s, compar);
else
addValueBt(&(*node)->right, data, s, compar);
}
When I call addValueBt in the main with two different ways (but normally seems to be the same thing) I don't get the same result
1st way:
int main(){
Node *root = NULL;
for(int i = 0; i < 10; i++)
addValueBt(&root, &i, 1, myCompar);
printBt(root,print);//print the whole tree
}
The display gives this:
10
10
10
10
10
10
10
10
10
10
2nd way:
int main(){
int a = 8, b = 9, c = 5, d = 1;
addValueBt(&root, &a, 1, myCompar);
addValueBt(&root, &b, 1, myCompar);
addValueBt(&root, &c, 1, myCompar);
addValueBt(&root, &d, 1, myCompar);
printBt(root,print);
}
The display:
1
5
8
9
"myCompar" compares between two integers
My question is: why it doesn't work when we use the function 'addValueBt' in the loop ?
(normally it should give the same result as for the other one )
Primary problem
As user3386109 correctly pointed out in a comment, the primary problem is that you're storing a pointer to the data in your tree, not a copy of the data. All the nodes end up pointing at the same location, so when that location changes, the value pointed at by the tree changes in all nodes at once.
Secondary issues
In a collection of comments (some of them responses to comment questions by Yasmine, the OP), I noted:
This is tangential to your main problem, but the parameter s is initially confusing. It's always 1 because you only allocate one node at a time. If it was larger, you'd waste the extra space that createNode() does allocate but does not initialize. You could stop using s (assume 1) without causing problems in the visible code.
I mean that in Node *createNode(void *data, size_t s) { Node *newNode = (Node *)malloc(s * sizeof(Node));, you allocate an array of Node structures of the size given by s. However, you initialize only the first structure allocated, and you don't record the size of the array anywhere. This doesn't matter because if you track the calls from main() to addValueBt() to createNode(), the value of s is always 1. But because it is always 1, you really have no need to pass it, so you can simplify the calls all the way down the calling chain.
Note that #user3386109: has identified the problem. You store the same pointer in each element of the tree, so when the pointed at value changes, all the elements of the tree change at the same time. And if the pointed at value goes out of scope, you get undefined behaviour. You either need to make a copy of the data in the createNode() function, which means that you need to know how big the data is so that you can allocate new space to store it, or you need to ensure that a different pointer is passed to the code each time, and those pointers remain valid until the tree is freed.
You can see with your working code, you pass a different pointer each time (a pointer to a different variable). When you repeatedly pass a pointer to the same variable, the same address is stored, so the current value stored at that address is used by all the nodes; they all have the same value.
Part of the problem comes from using void *data; instead of a simple int data;. For the immediate purposes, life would be much, much simpler if your data structure used int data;. You'd have:
Node *createNode(int key)
{
Node *newNode = (Node *)malloc(sizeof(Node));
newNode->data = data; newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
If you store void *, you really need to know how long the data you're storing pointers to is, so that you can make copies, etc. Your comparator can make assumptions about the length (and you'll be OK as long as those assumptions are correct). So, you'd need:
Node *createNode(void *data, size_t len)
{
void *copy = malloc(len);
memmove(copy, data, len);
Node *newNode = (Node *)malloc(s * sizeof(Node));
newNode->data = copy;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
Yasmine commented:
I know but I have to do that so that it can be used with other types like float or char.
At that point, I started to produce the code below.
Working code
Here's an offering dealing with the points made in my comments.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
typedef struct Node
{
void *data;
size_t datalen;
struct Node *left;
struct Node *right;
} Node;
static int cmp_dbl(const void *p1, const void *p2);
static int cmp_int(const void *p1, const void *p2);
static void freeBt(Node *node);
static void printBt(Node *node, void (*print)(const void *));
static void print_dbl(const void *p);
static void print_int(const void *p);
extern Node *createNode(void *data, size_t len);
extern void addValueBt(Node **node, void *data, size_t len, int (*compar)(const void *, const void *));
Node *createNode(void *data, size_t len)
{
void *copy = malloc(len);
// Error check allocation!
memmove(copy, data, len);
Node *newNode = (Node *)malloc(sizeof(*newNode));
// Error check allocation!
newNode->data = copy;
newNode->left = NULL;
newNode->right = NULL;
newNode->datalen = len;
return newNode;
}
void addValueBt(Node **node, void *data, size_t len, int (*compar)(const void *, const void *))
{
if (*node == NULL)
*node = createNode(data, len);
else if (compar((*node)->data, data) > 0)
addValueBt(&(*node)->left, data, len, compar);
else
addValueBt(&(*node)->right, data, len, compar);
}
int main(int argc, char **argv)
{
unsigned seed = time(0);
if (argc == 2)
seed = atoi(argv[1]);
srand(seed);
printf("Seed: %u\n", seed);
Node *root = NULL;
for (int i = 0; i < 10; i++)
addValueBt(&root, &i, sizeof(i), cmp_int);
printBt(root, print_int);
freeBt(root);
root = NULL;
for (int i = 0; i < 10; i++)
{
double d = (double)rand() / RAND_MAX * 1000.0 + (double)rand() / RAND_MAX;
addValueBt(&root, &d, sizeof(d), cmp_dbl);
}
printBt(root, print_dbl);
freeBt(root);
return 0;
}
static int cmp_int(const void *p1, const void *p2)
{
int v1 = *(int *)p1;
int v2 = *(int *)p2;
return (v1 > v2) - (v1 < v2);
}
static int cmp_dbl(const void *p1, const void *p2)
{
double v1 = *(double *)p1;
double v2 = *(double *)p2;
return (v1 > v2) - (v1 < v2);
}
static void print_int(const void *p)
{
printf("%d\n", *(int *)p);
}
static void print_dbl(const void *p)
{
printf("%8.3f\n", *(double *)p);
}
static void printBt(Node *node, void (*print)(const void *))
{
if (node != 0)
{
printBt(node->left, print);
print(node->data);
printBt(node->right, print);
}
}
static void freeBt(Node *node)
{
if (node != 0)
{
freeBt(node->left);
freeBt(node->right);
free(node);
}
}
Here's an example run:
Seed: 1511037421
0
1
2
3
4
5
6
7
8
9
87.907
118.694
140.163
170.833
343.940
412.792
422.254
530.731
557.656
936.981
What changed?
I dropped the parameter s to addValueBt() and createNode(), but added a parameter size_t len. That defines the length of the data. The length is stored in size_t datalen in the Node structure.
The code in createNode() makes a copy of the data it is passed and stores that copy in the tree. This ensures that each node is unaffected by changes to the values in the calling code.
What was added?
I added code for the int comparator (you called yours myCompar(); I called mine cmp_int() because I also wanted to work with double), and a double comparator cmp_dbl(). I added printing functions print_int() and printf_dbl() — renaming your print to print_int. I added memory release function freeBt(). I added code for printBt().
The code playing with the command line arguments allows you to specify a seed of your choosing. It's a bit sloppy; I should probably be using strtoul() instead of atoi(). But it allows you to specify a number on the command line to be used as the seed, which will give you repeatability when you need it. The seed is reported so you can reproduce results. This is helpful when playing with random numbers — sometimes you want randomness, and sometimes you want repeatability.
What I didn't do
I didn't fix the printing code so that the structure of the tree is visible. You just get a list of numbers.
The code doesn't really use the datalen member of the structure, but
it could be useful to check consistency, or for recording the length of strings.
Related
This question already has answers here:
Copy one pointer content to another
(4 answers)
Closed 1 year ago.
I'm working on doubly linked list and I came across the problem. I will paste parts of code step by step I try to explain what's happening.
So I have defined datatype:
typedef struct node {
void *data;
struct node *prev, *next;
} NODE;
In this part of add function might be something wrong. I've checked all scenarios but I don't want to paste unnecessary code.
void add(NODE **phead, NODE **ptail, void *data, int (*cmp)(const void*, const void*)){
NODE *p, *q, *new = (NODE*)calloc(1, sizeof(NODE));
new->data = data;
if(*phead == 0)
*phead = *ptail = new;
else if((*cmp)((*phead)->data, data) > 0){
new->next = *phead;
(*phead)->prev = new;
*phead = new;
}
When I was debugging code I saw that when function pointer is called same addresses were sent as arguments.
NODE *search(NODE *head, NODE *tail, const void *data, int (*cmp)(const void*, const void*)){
if(head == 0)
return 0;
while ((*cmp)(head->data, data) < 0 && (*cmp)(tail->data, data) > 0)
{
head = head->next;
tail = tail->prev;
}
if((*cmp)(head->data, data) == 0)
return head;
else if((*cmp)(tail->data, data) == 0)
return tail;
else
return 0;
}
Compare function which is argument of add and search function is:
int cmp_str(const void *a, const void *b){
return strcmp((const char*)a, (const char*)b);
}
Part of main function where both search and add are called:
int main(){
NODE *head = 0, *tail = 0;
char c, *data = (char*)calloc(20, sizeof(char));
do
{
printf("Add [A], delete [D], write [W], search [S], end [0]: ");
scanf("\n%c", &c);
if(c == 'A'){
get_string(&data);
NODE *p = search(head, tail, data, &cmp_str);
if(p){
p->data = data;
printf("Data updated!\n");
}
else{
add(&head, &tail, data, &cmp_str);
printf("Data added.\n");
}
}
So basically the thing that goes wrong is that only one data is saved. Here I work with strings but the parameters and variables of data is void*. So when I input add two nodes only the data of the last typed is saved. Also in main, every time except first p is found by search function even if it doesn't exist. As I told, debugger's saying that cmp_str receives two arguments of same address, which might be hint to find where the error is.
You are setting data pointer as same for each add operation. It seems you allocated once and using same memory for every cycle. If I'm wrong please correct me.
You need to allocate new memory and deep copy data pointer's content into new->data.
void add(NODE **phead, NODE **ptail, void *data, int (*cmp)(const void*, const void*)){
NODE *p, *q, *new = (NODE*)calloc(1, sizeof(NODE));
new->data = data;
...
The answer is very simple. It is quite common misunderstanding when people learn C.
The data pointer points always to the same memory location.
In add functions you simply assign this reference to all nodes. In C = does not copy the memory referenced by the pointers only assigns the reference.
You need to allocate it at every interaction (in main) or copy it in the add function.
void add(NODE **phead, NODE **ptail, void *data, size_t data_size, int (*cmp)(const void*, const void*)){
NODE *p, *q, *new = calloc(1, sizeof(*new));
//check if calloc did not return NULL
new -> data = calloc(1, data_size);
//check if calloc did not return NULL
memcpy(new->data, data, data_size);
// ...
Some additional remarks:
Use objects not types in sizeof.
Do not cast the result of malloc/calloc. If compiler is giving you errors the it is an indication that you compile the C code using C++ compiler which is not a good idea.
I am trying to bubble sort linkedlist based on int value which I hold in char array.
I know that I need to do following steps;
void bubbleSort(struct Node *start)
{
int swapped, i;
struct Node *ptr1;
struct Node *lptr = NULL;
/* Checking for empty list */
if (start == NULL)
return;
do
{
swapped = 0;
ptr1 = start;
while (ptr1->next != lptr)
{
if (ptr1->data > ptr1->next->data)
{
swap(ptr1, ptr1->next);
swapped = 1;
}
ptr1 = ptr1->next;
}
lptr = ptr1;
}
while (swapped);
}
and
/* function to swap data of two nodes a and b*/
{
int temp = a->data;
a->data = b->data;
b->data = temp;
}
but as I said above I have created a struct with char value;
struct nodeForLinkedList
{
char frequency[STRING_LEN]; **// Purpose of this is to hold int value from text file.**
struct nodeForLinkedList *next;
};
void swap(struct nodeForLinkedList *a, struct nodeForLinkedList *b)
{
char temp = a->frequency;
a->frequency = b->frequency; // atoi(b->frequency) or strtol
b->frequency = temp;
}
here I could use atoi function to get int value from char array. atoi function help me to get int value from 'frequency' array
But I don't know how to change a->frequency value with b->frequency value.
Any help would be appreciated
Thanks in advance
The simplest solution is to use one of the string or memory copying functions from the library:
#include <string.h>
void swap(struct nodeForLinkedList *a, struct nodeForLinkedList *b)
{
char temp[sizeof(a->frequency)];
strcpy(temp, a->frequency);
strcpy(a->frequency, b->frequency);
strcpy(b->frequency, temp);
}
The above use of strcpy assumes that the frequency member contains a null-terminated string. You could use memcpy to copy the whole array regardless of null-termination:
#include <string.h>
void swap(struct nodeForLinkedList *a, struct nodeForLinkedList *b)
{
char temp[sizeof(a->frequency)];
memcpy(temp, a->frequency, sizeof(temp));
memcpy(a->frequency, b->frequency, sizeof(temp));
memcpy(b->frequency, temp, sizeof(temp));
}
So there are lots of examples of using qsort() with structures, pointers, etc. But none of them seem to sort correctly in my implementation.
This is an overview of my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
int value;
};
typedef struct node Node;
int compare(const void *p1, const void *p2);
int main()
{
Node *myArray[10];
Node *node1, *node2, *node3;
int i;
node1 = (Node *)malloc(sizeof(Node));
node1->value = 10;
myArray[0] = node1;
node2 = (Node *)malloc(sizeof(Node));
node2->value = 7;
myArray[1] = node2;
node3 = (Node *)malloc(sizeof(Node));
node3->value = 12;
myArray[2] = node3;
for (i=0; i<3; i++) {
printf("Element %i: %i\n", i, myArray[i]->value);
}
printf("-------------\n");
qsort(myArray, 3, sizeof(Node*), compare);
for (i=0; i<3; i++) {
printf("Element %i: %i\n", i, myArray[i]->value);
}
return 0;
}
int compare(const void *p1, const void *p2)
{
Node *node1 = (Node*) p1;
Node *node2 = (Node*) p2;
return node1->value - node2->value;
}
This code is to demonstrate my issue, so please don't have a rant at me for semantics! The extra unused space in the array is intentional. :p
So as far as I'm aware, and from what I'm reading online, this should work. But it doesn't. For some reason it starts sorting through garbage values in the compare function.
I require the array to often be larger than the values within it, so hoped the second argument of the qsort() function would limit it to only the first 3 elements in this case. But it seems to be ignoring that.
Any ideas what's causing this strange behaviour?
When you pass *myArray as the first argument to the qsort function, it's like passing myArray[0], which is definitely not the correct pointer (and will lead to undefined behavior and most likely some weird behavior like sorting "garbage" data).
Either let the array decay to a pointer to the first element by using plain myArray, or explicitly specify the first element using &myArray[0].
Joachim has solved one problem, there's another. qsort passes pointers to the array elements to compare even if they are already pointers. So compare is getting Node **, a double pointer. You can see this if you print node->value inside compare.
Cast accordingly.
static int compare(const void *p1, const void *p2)
{
const Node *node1 = *(const Node **)p1;
const Node *node2 = *(const Node **)p2;
printf("cmp %d %d\n", node1->value, node2->value);
return node1->value - node2->value;
}
I have been assigned to program a generic stack in ANSI C. It is meant to be for primitive datatypes. Until here there was no big problem whatsoever.
Afterwards I was asked to reprogram my application so that even complex data types can be used on my stack. I have searched and researched for the last week and I found nothing that could be helpful enough.
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stddef.h>
#include "genstacklib.h"
void (*freefn) (void*);
/*
* ToDo
*/
void GenStackNew(genStack *s, int elemSize, void (*freefunk) (void*))
{
s->elems = malloc (elemSize * GenStackInitialAllocationSize);
freefn = freefunk;
assert (s->elems != NULL);
s->elemSize = elemSize;
s->logLength = 0;
s->allocLength = GenStackInitialAllocationSize;
}
/*
* ULStackPush adds an element to the stack and allocates new memory if
* needed. If there is not enough memory, ULStackPush does nothing.
*/
void GenStackPush (genStack *s, const void *elemAddr)
{
/*assert (sizeof(*elemAddr) == s->elemSize);*/
assert (s->elems != NULL);
if (s->logLength == s->allocLength)
{
void *temp = NULL;
temp = realloc (s->elems, 2 * s->allocLength * s->elemSize);
assert (temp != NULL);
s->allocLength = 2 * s->allocLength;
s->elems = temp;
}
memcpy(currentval(s), elemAddr, s->elemSize);
s->logLength = s->logLength + 1;
}
void GenStackPop (genStack *s, const void *elemAddr)
{
assert (s->elems != NULL);
assert (s->logLength != 0);
(s->logLength)--;
memcpy((void *)elemAddr, currentval(s), s->elemSize);
}
void *currentval(genStack *s)
{
assert (s->elems != NULL);
return ((size_t*)s->elems + s->logLength * s->elemSize);
}
bool GenStackEmpty (const genStack *s)
{
assert (s->elems != NULL);
return s->logLength == 0;
}
void GenStackDispose (genStack *s)
{
assert (s->elems != NULL);
s->logLength = 0;
free (s->elems);
freefn();
}
/*
* ToDO
*/
void *freefn (void *) {
free
And my header data is:
#ifndef GENSTACKLIB_H
#define GENSTACKLIB_H
#include <stdbool.h>
#define GenStackInitialAllocationSize 4
typedef struct
{
void *elems;
int elemSize;
int logLength;
int allocLength;
} genStack;
void GenStackNew (genStack * s, int elemSize);
bool GenStackEmpty (const genStack * s);
void GenStackPush (genStack * s, const void *elemAddr);
void GenStackPop (genStack * s, const void *elemAddr);
void GenStackDispose (genStack * s);
void *currentval(genStack *s);
#endif
In the first block of code, I believe that what has to be done is in the ToDo markings.
How can I make it to use my stack for complex data types?
Thanks in advance
I dont see any problem with "complex" types like strings... there is no real difference bewteen pointer to string and pointer to int. So just store pointers (or pointers to pointers) and that should work.
So instead of element to be "int".. element is pointer to pointer.
Basic idea in form of very "pseudo" C code
typedef struct Wrapper
{
void * primitiveData;
} Wrapper;
void PrimitivePush(void * data)
{
Wrapper * w = malloc();
w->primitiveData = malloc();
memcpy(w->primitiveData, data);
ClassicComplexTypePush(&w)
}
ClassicComplexTypePush(void ** data)
{
push data to stack
}
Consider using a singularly linked list for implementation, since when
using a stack, we don't know how many items may be needed.
Use a byte* or (char*) to store the contents of memory, instead of a void* (which would also work, but we may need to pad the allocation, to include structs)
Copy memory into a new allocation, which is pushed onto the stack,
then delete that used upon pop.
each node has to be of the same type, or at-least the same size,
errors using wrong type though may be undesired
pop can be either used to check if the stack is empty by passing (NULL)
or to actually pop the stack, by referencing the memory you want to set.
typedef unsigned char byte;
Create the structures which will be used to keep track of the stack
struct gStackNode {
byte *data;
struct gStackNode *next;
};
struct gStack {
unsigned size;
struct gStackNode *head;
};
Initialize the stack, including the size of the type we will be using
void stack_initalize(struct gStack *stk, unsigned size) {
if (!stk)
return;
stk->size = size;
stk->head = (void*)0;
}
Always, we need to manually free the stack, in-case not all were popped
void stack_free(struct gStack *stk) {
if (!stk)
return;
struct gStackNode *temp;
/* step through the remaining stack, deleting each item */
while(stk->head) {
temp = stk->head->next;
free((byte*)stk->head->data);
free((struct gStackNode *)stk->head);
stk->head = temp;
}
}
push an item onto the stack
void stack_push(struct gStack *stk, void *data) {
struct gStackNode *node = (struct gStackNode*)malloc(sizeof(struct gStackNode));
struct gStackNode *temp = stk->head;
node->next = temp;
node->data = (byte*)malloc(sizeof(byte)*(stk->size));
byte * src = (char*)(data);
byte * dest = (char*)(node->data);
unsigned n = stk->size;
/* fill the new allocation with source data */
for(;n;n--)
*(dest++) = *(src++);
/* the node becomes the new head */
stk->head = node;
}
Sometimes we don't want to use a local variable ie: stack_pop_(stack, &type) we can use stack_push_arg_no_ref(stack, 10).
void stack_push_arg_no_ref(struct gStack *stk, void *data) {
stack_push(stk, &data);
}
Now we can pop, and use the same to peek, passing (NULL) to data will result in a peek,
returning (1) if there is an item in the stack, and a (0) if its empty
int stack_pop(struct gStack *stk, void * data) {
if (!stk)
return 0;
if (!stk->head)
return 0;
if (data == (void*)0) {
/*
simply check to see if the stack is empty or not
don't actually pop the stack
*/
return ((!stk->head == (void*)0));
} else {
struct gStackNode *next = stk->head->next;
struct gStackNode *node = stk->head;
unsigned i;
byte *c_temp = (byte*)data;
for(i=0;i<stk->size;i++)
*c_temp++ = node->data[i];
free((byte*)node->data);
free((struct gStackNode*)node);
stk->head = next;
}
}
Finally we can implement the stack
using any ANSI C data types
the size of a character string needs to be fixed
structs can also be used
Using a character string
CAUTION, for this example, the strings need to be NULL terminated, though
it is possible to use non-NULL terminated strings
char ta[32] = "ta: text 1";
char tb[32] = "tb: text 2";
char tc[32];
struct gStack stack_char; stack_initalize(&stack_char, sizeof(ta));
stack_push(&stack_char, ta);
stack_push(&stack_char, tb);
while (stack_pop(&stack_char, &tc))
printf("%s\n", tc);
be sure to free the stack
stack_free(&stack_char);
Using integers
int a = 120, b = -32, c;
struct gStack stack_int; stack_initalize(&stack_int, sizeof(int));
stack_push(&stack_int, &a);
stack_push(&stack_int, &b);
/* or we can use */
stack_push_arg_no_ref(&stack_int, 1776);
/* we can now see the contents of the stack */
while (stack_pop(&stack_int, &c))
printf("%d\n", c);
stack_free(&stack_int);
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(¤t->left, &ret, size);
traverse(¤t->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().