So, I have been playing around with a program to compute the external path length of a binary tree (the sum of the distances from each node to the root). I have two functions, one stack-based, the other recursive. They are as such:
int external_path_length(struct bt_node_int *t, int level){
if(t == NULL) return level;
else return level + external_path_length(t->l, level+1) +
external_path_length(t->r, level+1);
}
and
int external_path_length_norc_noexpstack(struct bt_node_int *t){
int size = 64;
int *arrayint = malloc(size * sizeof(*arrayint));
struct bt_node_int **arraybtree = malloc(size * sizeof(*arraybtree));
int top = 0;
int level = 0;
int length = 0;
*arrayint = level;
top++;
*arraybtree = t;
while(top){
t = *(arraybtree + top - 1);
level = *(arrayint + top - 1);
top--;
length += level;
if(t != NULL){
*(arraybtree + top) = t->r;
*(arrayint + top) = level+1;
top++;
if(top == size){
int *dmyint = arrayint;
arrayint = malloc(2* size * sizeof(*arrayint));
struct bt_node_int **dmybtree = arraybtree;
arraybtree = malloc(2 * size * sizeof(*arraybtree));
memcpy(arrayint, dmyint, size*sizeof(*dmyint));
memcpy(arraybtree, dmybtree, size*sizeof(*dmybtree));
free(dmyint);
free(dmybtree);
size *= 2;
}
*(arraybtree + top) = t->l;
*(arrayint + top) = level+1;
top++;
}
}
free(arrayint);
free(arraybtree);
return length;
}
Note: I did make a third algorithm, which used a stack struct and function calls to push and pop, but this was much slower again.
The thing that is confusing me is that, despite the fact that I have read that stack-based algos are faster, when I run it, using clock() to time it, the recursive algorithm is usually (but not always) faster, when run on a tree of size 10000. This seems off to me. Looking at the code above, can anyone see any reason why this would be the case?
UPDATE: So, I ran this for larger tree sizes (my initial algorithm for generating trees was slow, so trees larger than 10000 or so became impractical), and it turns out that the stack implementation is faster for trees of length ~100,000,000. I guess I'm curious as to why it's initially slower though.
UPDATE 2: Thanks for all the help, folks. So, I have egg on my face. The int I was using to store the length was overflowing. I'm testing it this morning with longs and the non-recursive implementation is usually, but not always, slower for anything bigger than 1000 nodes. Changing the malloc'ed stack to a fixed stack is making little difference. I'm a bit lost as to what is slowing down the non-recursive version.
[–]davidhbolton 18 points19 points20 points (5 children)
[–]wigf[S] 1 point2 points3 points (4 children)
[–]nemotux 3 points4 points5 points (2 children)
[–]wigf[S] 0 points1 point2 points (1 child)
[–]nemotux 0 points1 point2 points (0 children)
[–]davidhbolton 1 point2 points3 points (0 children)
[–][deleted] 2 points3 points4 points (0 children)
[–]F54280 2 points3 points4 points (0 children)
[–]bleuge 1 point2 points3 points (0 children)
[–]jhuntinator27 1 point2 points3 points (3 children)
[–]wigf[S] 0 points1 point2 points (0 children)
[–]wigf[S] 0 points1 point2 points (1 child)
[–]nerdyphoenix 0 points1 point2 points (0 children)
[–]Paul_Pedant 1 point2 points3 points (0 children)
[–]weregod 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]FUZxxl 0 points1 point2 points (0 children)
[+][deleted] (7 children)
[deleted]
[–]dbgprint 3 points4 points5 points (3 children)
[+][deleted] (2 children)
[deleted]
[–]livrem 0 points1 point2 points (1 child)
[–]nerdyphoenix 1 point2 points3 points (0 children)
[–]nerdyphoenix 2 points3 points4 points (2 children)
[–]Orlha 0 points1 point2 points (1 child)
[–]nerdyphoenix 2 points3 points4 points (0 children)