Binary Tree Preorder Traversal in C [closed] - c

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I am having a pointer or memory-related problem here:
void nodesVal(struct TreeNode* root, int *returnSize, int **returnArray){
if (root != NULL)
{
*(returnSize) = *(returnSize) + 1;
*returnArray[*(returnSize) - 1] = root->val;
// I get a runtime memory error whenever I try to access ths array
if (root->left != NULL) nodesVal(root->left, returnSize, returnArray);
if (root->right != NULL) nodesVal(root->right, returnSize, returnArray);
}
}
int* preorderTraversal(struct TreeNode* root, int* returnSize){
int *returnArray = (int*)malloc(sizeof(int) * 100);
*returnSize = 0;
nodesVal(root, &returnSize, &returnArray);
return returnArray;
}
Does anyone see where I am going wrong?

Major changes: //-------->
Minor changes: //
#include <stdio.h>
#include <stdlib.h>
struct TreeNode
{
int val;
struct TreeNode *left;
struct TreeNode *right;
};
void nodesVal(struct TreeNode *root, int *returnSize, int **returnArray)
{
if (root != NULL)
{
//-------> (*returnArray)[0] instead of *returnArray[0] ----> [] has higher priority than *
// I changed the order of those two lines so that I don't say size++ and then use size-1 (you can ignore this)
(*returnArray)[*(returnSize)] = root->val;
*(returnSize) = *(returnSize) + 1;
// when you enter this, you already check for NULL, so I removed (if) --- However, this can be ignored
nodesVal(root->left, returnSize, returnArray);
nodesVal(root->right, returnSize, returnArray);
}
}
int *preorderTraversal(struct TreeNode *root, int *returnSize)
{
int *returnArray = (int *)malloc(sizeof(int) * 100);
*returnSize = 0;
// ---------> you were passing &returnSize (int**). However, the function needs (int*). So, pass returnSize
nodesVal(root, returnSize, &returnArray);
return returnArray;
}
void constructNode(struct TreeNode**root,struct TreeNode*left,struct TreeNode* right,int val){
(*root)->left = left;
(*root)->right = right;
(*root)->val = val;
}
int main()
{
struct TreeNode*root = (struct TreeNode*)malloc(sizeof(struct TreeNode));
struct TreeNode*node1 = (struct TreeNode*)malloc(sizeof(struct TreeNode));
struct TreeNode*node2 = (struct TreeNode*)malloc(sizeof(struct TreeNode));
struct TreeNode*node3 = (struct TreeNode*)malloc(sizeof(struct TreeNode));
constructNode(&root,node1,node2,1);
constructNode(&node1,node3,NULL,2);
constructNode(&node2,NULL,NULL,3);
constructNode(&node3,NULL,NULL,4);
int* returnedSize = malloc(sizeof(int));
int* arr = preorderTraversal(root,returnedSize);
for (int i = 0; i < *returnedSize; i++)
{
printf("%d ",arr[i]);
}
printf("\n");
free(arr);
free(returnedSize);
free(root);
free(node1);
free(node2);
free(node3);
return 0;
}

Related

C Language - Tried to make an array stack data structure to implement a undo/redo "prototype", why isn't it working? :(

Basically I made a create_app() function to allocate 2 nodes in the stack, each having a pointer to an array[max]; undo() pops the last element, and before returning it, it adds it into the REDO node's array. redo() does the opposite, pops the last element in it's array, putting it into Undo's array before returning it. What did I do wrong ?
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#define EMPTY_TOS (-1)
typedef struct node *node_ptr;
struct node
{
int arr_size;
int tos;
int *arr_stack;
node_ptr next;
};
typedef node_ptr STACK;
STACK
create_app(int max)
{
STACK UNDO = (STACK) malloc(sizeof(struct node));
STACK REDO = (STACK) malloc(sizeof(struct node));
{
UNDO->arr_stack == (int *) malloc(max * sizeof(int));
REDO->arr_stack == (int *) malloc(max * sizeof(int));
if(UNDO->arr_stack != NULL){printf("Out of space!");}
else
{
UNDO->tos = EMPTY_TOS;
REDO->tos = EMPTY_TOS;
UNDO->arr_size = max;
REDO->arr_size = max;
UNDO->next = REDO;
REDO->next = UNDO;
return UNDO;
}
}
}
int
isEmpty(STACK S)
{
return(S->tos==-1);
}
int
isFull(STACK S)
{
return(S->tos>=S->arr_size-1);
}
void
push(int x, STACK S)
{
if(isFull(S)){printf("Stack full!");}
else
{
S->arr_stack[++S->tos] = x;
}
}
int
undo(STACK S)
{
if(isEmpty(S)){printf("Nothing to undo!");}
else
{
S->next->arr_stack[++S->next->tos] = S->arr_stack[S->tos];
printf("%d",S->arr_stack[S->tos--]);
}
}
int
redo(STACK S)
{
if(isEmpty(S->next)){printf("Nothing to redo!");}
else
{
int temp = S->next->arr_stack[S->next->tos];
push(S->next->arr_stack[S->next->tos], S);
S->next->tos--;
printf("%d",temp);
}
}
int main()
{
STACK app = create_app(5);
push(1,app);
push(2,app);
push(3,app);
undo(app);
undo(app);
redo(app);
redo(app);
/* Expected output: 3223 */
return 0;
}
Some small errors were in your code, like these ones in create_app() which seem like typos.
UNDO->arr_stack == (int *) malloc(max * sizeof(int));
REDO->arr_stack == (int *) malloc(max * sizeof(int));
^
|
if(UNDO->arr_stack != NULL){printf("Out of space!");}
^
|
...
and some int returning functions did not return anything in the else part which gave some warnings.
Here is the modified code, which worked fine for me
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#define EMPTY_TOS (-1)
typedef struct node* node_ptr;
struct node
{
int arr_size;
int tos;
int *arr_stack;
node_ptr next;
};
typedef node_ptr STACK;
STACK
create_app(int max)
{
STACK UNDO = (STACK) malloc(sizeof(struct node));
STACK REDO = (STACK) malloc(sizeof(struct node));
{
UNDO->arr_stack = (int *) malloc(max * sizeof(int));
REDO->arr_stack = (int *) malloc(max * sizeof(int));
if(UNDO->arr_stack == NULL){printf("Out of space!");
return NULL;}
else
{
UNDO->tos = EMPTY_TOS;
REDO->tos = EMPTY_TOS;
UNDO->arr_size = max;
REDO->arr_size = max;
UNDO->next = REDO;
REDO->next = UNDO;
return UNDO;
}
}
}
int
isEmpty(STACK S)
{
return (S->tos == -1);
}
int
isFull(STACK S)
{
return (S->tos >= S->arr_size-1);
}
void
push(int x, STACK S)
{
if(isFull(S)){printf("Stack full!");}
else
{
S->arr_stack[++S->tos] = x;
}
}
void
undo(STACK S)
{
if(isEmpty(S)){printf("Nothing to undo!");}
else
{
S->next->arr_stack[++S->next->tos] = S->arr_stack[S->tos];
printf("%d",S->arr_stack[S->tos--]);
}
}
void
redo(STACK S)
{
if(isEmpty(S->next)){printf("Nothing to redo!");}
else
{
int temp = S->next->arr_stack[S->next->tos];
push(S->next->arr_stack[S->next->tos], S);
S->next->tos--;
printf("%d",temp);
}
}
int main()
{
STACK app = create_app(5);
push(1,app);
push(2,app);
push(3,app);
undo(app);
undo(app);
redo(app);
redo(app);
/* Expected output: 3223 */
return 0;
}
Result:
3223
However, always take precaution in deallocating the memory malloced using free().

Understanding how to convert void* and int* in C

I have written the following code:
typedef struct List {
struct List* next;
void *value;
} List;
void freeList(List* list, void destroyElement(void*)) {
while(list != NULL) {
destroyElement(list->value);
struct List* n = list;
list = list->next;
free(n);
}
}
struct List* arr2list(void** array, int length, void* cpyElement(void*), void (*destroyElement)(void*)) {
struct List* head = NULL;
struct List** tail = &head;
for(int i = 0; i < length; i++) {
*tail = calloc(1, sizeof(struct List));
printf("array[%d] = %d\n",i,*(((int*)array)+i));
if (*tail == NULL) {
freeList(head, destroyElement);
return NULL;
}
tail[0]->value = cpyElement(array[i]);
tail = &(tail[0]->next);
}
*tail = NULL;
return head;
}
void printList(List* list, void echoElement(void*)) {
while (list != NULL) {
echoElement(list->value);
list = list->next;
}
}
void destroyElement(void* el) {
if (el != NULL) {
struct List* node = el;
node->next = NULL;
free(node);
}
}
void* cpyElement(void* el) {
int *p = malloc(sizeof(*p));
*p = *(int *) el;
return p;
}
void echoElement(void* el) {
if (el != NULL) {
printf("%d ", *(int *) el);
}
}
int main(int argc, char** argv) {
int array_length = argc - 1;
int* array = (int*) malloc(sizeof(*array) * array_length);
for (int i = 0; i < array_length; i++){
*(array + i) = atoi(argv[i + 1]);
}
struct List* root = arr2list((void*) array,array_length,cpyElement, destroyElement);
printList(root,echoElement);
freeList(root,destroyElement);
free(array);
return 0;
}
The problem is with tail[0]->value = cpyElement(array[i]);. I get a segmentation fault error for this part. If I write it cpyElement(((int*)array)+i); it works but I want the function arr2list to be generic and not to mention int. How can I solve it? I think that I understand it's impossible to convert void* to int* because it does not know which size to use so is it possible to hear some suggestions on how to approach this issue so it will work? Maybe change the array argument?
You need to create an array of pointers to ints and then pass that. Yes, it's a lot of malloc calls, but it's necessary (since you're using void *).
int main(int argc, char** argv) {
struct List *root;
int i, array_length = argc - 1;
int** array = malloc(sizeof(*array) * array_length);
for (i = 0; i < array_length; i++){
array[i] = malloc(sizeof(*array[i]));
*array[i] = atoi(argv[i + 1]);
}
root = arr2list((void **)array,array_length,cpyElement, destroyElement);
printList(root,echoElement);
freeList(root,destroyElement);
free(array);
return 0;
}
This code:
void destroyElement(void* el) {
if (el != NULL) {
struct List* node = el;
node->next = NULL;
free(node);
}
}
will then need to be changed to (in fact, it only worked before due to a platform-specific bug):
void destroyElement(void* el) {
free(el);
}
Also, do not cast the result of malloc. That means no (int *)malloc(...). Just use malloc(...), it's safer and doesn't cover up errors.
The problem with void * is that while you can freely convert other pointer types to void * and back again and get the original pointer back, you need to do that directly -- you can't pass a void ** where it points at anything other than void *'s and expect it to work.
Even worse, in your case, you're passing an array of int where an array of void * are expected. You can deal with this by casting yout ints to intptr_t and thence to void * to store in your list -- you'll have to do that double-cast back again to get them out again:
void echoElement(void* el) {
printf("%d ", (int)(intptr_t)el);
}
int main(int argc, char** argv) {
int array_length = argc - 1;
void *array = malloc(sizeof(*array) * array_length);
for (int i = 0; i < array_length; i++) {
array[i] = (void *)(intptr_t)atoi(argv[i + 1]);
}
struct List* root = arr2list((void*) array,array_length,cpyElement, destroyElement);
printList(root,echoElement);

Simple C trie program goes wrong (segmentation fault) [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
In order to understand tries I am creating this very simple C program that takes from user 10 nums from 0 to 9 as children of the trie. The final step is to print this nums with the function print, but I am getting a segmentation fault:
#include <stdio.h>
#include <stdlib.h>
typedef struct list
{
int data;
struct list *ar[10];
} list;
void insert(list *head);
void print(list *head);
int main(void)
{
printf("hello\n");
list *root = malloc(sizeof(list));
insert(root);
print(root);
}
void insert(list *head)
{
int a, i;
if (head == NULL) {
return;
}
for (i = 0; i < 10; i++) {
printf("Give Num 0-9\n");
scanf("%i", &a);
head->ar[a] = malloc(sizeof(head));
head = head->ar[a];
head->data = a;
}
}
void print(list *head)
{
if (head == NULL) {
return;
}
while (head != NULL) {
for (int i = 1; i < 10; i++) {
if (head->ar[i] != NULL) {
printf("%i", i);
head = head->ar[i];
break;
}
}
}
printf("\n");
}
There are several issues with your code:
The first mention of malloc doesn't actually initialize the memory (the ar field). You should initialize it properly
list *root = malloc(sizeof(list));
Is missing initialization, e.g.
root->data = 0;
for (size_t ii = 0; ii < 10; ii++) {
root->ar[ii] = NULL;
}
When you are actually gathering input, you allocate only enough memory for the pointer, not for the actual list itself.
head->ar[a] = malloc(sizeof(head));
should be initialized as above (head = malloc(sizeof(list)); for (size_t ...
There seems to be an infinite loop when actually running your program (after correcting all these issues).
EDIT: Remove calloc...

Dynamic stack in C [pop crash] [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
Im making a program to convert a decimal int to binary using a dynamic stack.
It crashes on the last pop.
ex. num: 4 output: 10crash
#include <stdio.h>
struct stack {
struct stack *prev;
int val;
struct stack *next;
};
struct stack *first,*cur,*tmp;
struct stack *GETNODE(){
struct stack *pt = (struct stack *)malloc(sizeof(struct stack));
};
int counter=1;
void push(int val){
tmp=GETNODE();
tmp->prev=NULL;
tmp->val=val;
tmp->next=NULL;
if(first==NULL){
first=tmp;
cur=first;
}else{
tmp->prev=cur;
cur->next=tmp;
cur=tmp;
}
counter++;
};
int pop(){
int val=tmp->val;
cur=tmp->prev;
free(tmp);
tmp=cur;
tmp->next=NULL;
counter--;
return(val);
};
main(){
int num = 4;
while(num!=0){
push(num%2);
num/=2;
}
while(counter!=1){
printf("%d ",pop());
}
}
The problem is in your pop function. If you think about how it operates, in the final pass you will free(tmp), which is currently pointing to the very first item. After you free it, you then assign:
tmp->next=NULL;
You are trying to dereference an invalid pointer at this point.
I made a lot of changes to your code. Mainly, it was far too complicated - only a singly linked list was needed, and you don't need a counter - just track the list pointer. Your GETNODE() function did not return a value, causing undefined behaviour in the calling function. I simplified that too, there is no need for a separate function to allocate memory because malloc() already does that.
#include <stdio.h>
#include <stdlib.h>
struct stack {
struct stack *prev;
int val;
};
struct stack *first = NULL;
void push(int val){
struct stack *pt = malloc(sizeof(struct stack));
if (pt == NULL){
printf ("Bad call to malloc()\n");
exit (1);
}
pt->prev=first;
pt->val=val;
first = pt;
}
int pop(){
int val;
struct stack *pt = first;
if (first == NULL)
return -1;
val=first->val;
first = first->prev;
free(pt);
return(val);
}
void dec2bin(int num){
printf("%-5d", num);
while(num!=0){
push(num%2);
num/=2;
}
while(first){
printf("%d",pop());
}
printf("\n");
}
int main(void){
dec2bin (4);
dec2bin (129);
dec2bin (160);
return 0;
}
Program output:
4 100
129 10000001
160 10100000
I change some part of your code and your code working now.
#include <stdio.h>
#include <stdlib.h>
struct stack {
struct stack *prev;
int val;
struct stack *next;
};
struct stack *first, *cur, *tmp;
int counter = 0;
struct stack *GETNODE()
{
return malloc(sizeof(struct stack));
}
void push(int val)
{
tmp = GETNODE();
tmp->prev = NULL;
tmp->val = val;
tmp->next = NULL;
if (first == NULL) {
first = tmp;
cur = first;
} else {
tmp->prev = cur;
cur->next = tmp;
cur = tmp;
}
counter++;
}
int pop(void)
{
int val = cur->val;
tmp = cur;
cur = cur->prev;
free(tmp);
counter--;
return val;
}
int main(int argc, char *argv[])
{
int num;
scanf("%d", &num);
while (num != 0) {
push(num % 2);
num /= 2;
}
while (counter != 0)
printf("%d ", pop());
printf("\n");
}

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