c - Function to turn a Binary Tree into the sums of all nodes below each node; segmentation fault if I don't create a new binary tree -
i want create function sum nodes below node including own value, this
3 6 / \ / \ 1 2 turn 1 2
link exercise in question: https://codeboard.io/projects/16280
here's defenition of abin , call function:
typedef struct nodo { int valor; struct nodo *esq, *dir; } *abin; abin somasaca (abin a);
this version works, though don't because creates new binary tree:
int getsums(abin a){ int esq, dir; if(a == null) return 0; esq = getsums(a->esq); dir = getsums(a->dir); return(a->valor + esq + dir); } abin somasaca (abin a) { abin b, *res; res = &b; if(a!=null){ b = newabin(getsums(a), null,null); b->esq= somasaca(a->esq); b->dir= somasaca(a->dir); } if(a==null) b=null; return *res; }
and version gives me segmentation fault:
abin somasaca (abin a) { if(a == null) return null; a->valor = getsums(a); a->esq = somasaca(a->esq); a->dir = (somasaca(a->dir)); return a; }
the thing is, if put a->valor = getsums(a); in middle don't segfault (but wrong values if height of tree higher 2). causing segmentation fault , why can't without creating new bin tree? thanks.
it nuisance when have create mcve fragments of program. however, it's doable — it's pain, doable.
here's variation on code. of 115 lines shown, 35 wrote in question — roughly. so, had create twice code create semi-plausible mcve.
#include <assert.h> #include <stdio.h> #include <stdlib.h> typedef struct abin_s *abin; struct abin_s { int valor; abin esq; abin dir; }; abin somasaca_ok(abin a); int getsums(abin a); abin somasaca(abin a); static abin newabin(int valor, abin esq, abin dir) { abin ab = malloc(sizeof(*ab)); if (ab == 0) { fprintf(stderr, "failed malloc %zu bytes\n", sizeof(*ab)); exit(exit_failure); } ab->valor = valor; ab->esq = esq; ab->dir = dir; return ab; } int getsums(abin a) { if (a == null) return 0; int esq = getsums(a->esq); int dir = getsums(a->dir); return(a->valor + esq + dir); } abin somasaca_ok(abin a) { abin b, *res; res = &b; if (a != null) { b = newabin(getsums(a), null, null); b->esq = somasaca_ok(a->esq); b->dir = somasaca_ok(a->dir); } if (a == null) b = null; return *res; } abin somasaca(abin a) { // remove unused b if (a != null) { a->valor = getsums(a); a->esq = somasaca(a->esq); a->dir = somasaca(a->dir); } return a; } static void print_postorder(abin node) { if (node != 0) { print_postorder(node->esq); print_postorder(node->dir); printf("valor = %d\n", node->valor); } } static void print_tree(const char *tag, abin node) { printf("tree: %s\n", tag); print_postorder(node); } static void free_tree(abin node) { if (node != 0) { free_tree(node->esq); free_tree(node->dir); free(node); } } int main(void) { abin root = newabin(3, 0, 0); abin esq = newabin(1, 0, 0); abin dir = newabin(2, 0, 0); root->esq = esq; root->dir = dir; print_tree("before", root); abin eval = somasaca(root); assert(eval == root); print_tree("after", root); eval = somasaca_ok(root); assert(eval != root); print_tree("second time", root); free(root); free(esq); free(dir); free_tree(eval); }
i created somasaca_ok()
working function, marginally cleaning up. somasaca()
'non-working' function, cleaned up. don't think changed functionality of either. note tree building code doesn't attempt use function build — you've not shown such function. creates 3 nodes , links them manually.
the code compiles cleanly under gcc 6.1.0 on mac os x 10.11.5 command line:
$ gcc -o3 -g -std=c11 -wall -wextra -wmissing-prototypes -wstrict-prototypes \ > -wold-style-definition -werror abin.c -o abin $
when run under valgrind
, gets clean bill of health.
$ ./abin tree: before valor = 1 valor = 2 valor = 3 tree: after valor = 1 valor = 2 valor = 6 tree: second time valor = 1 valor = 2 valor = 6 $
on basis of see, second lot of code, 1 claim fails, works correctly, 1 claim succeeds doesn't addition (the last valor
should 9
on second time).
i'm bit dubious way functions work. i'd expect somasaca()
evaluating sub-trees before summing modified trees. works side-effect of minimal tree. maybe should using:
abin somasaca(abin a) { if (a != null) { a->esq = somasaca(a->esq); a->dir = somasaca(a->dir); a->valor = getsums(a); } return a; }
i'm not convinced needs return value, either, collateral changes, use:
void somasaca(abin a) { if (a != null) { somasaca(a->esq); somasaca(a->dir); a->valor = getsums(a); } }
extending testing more extensive trees left exercise correct tree-creation function code.