diff options
Diffstat (limited to 'lib/rbtree.c')
| -rw-r--r-- | lib/rbtree.c | 40 | 
1 files changed, 40 insertions, 0 deletions
| diff --git a/lib/rbtree.c b/lib/rbtree.c index c0e31fe2fabf..65f4effd117f 100644 --- a/lib/rbtree.c +++ b/lib/rbtree.c @@ -518,3 +518,43 @@ void rb_replace_node(struct rb_node *victim, struct rb_node *new,  	*new = *victim;  }  EXPORT_SYMBOL(rb_replace_node); + +static struct rb_node *rb_left_deepest_node(const struct rb_node *node) +{ +	for (;;) { +		if (node->rb_left) +			node = node->rb_left; +		else if (node->rb_right) +			node = node->rb_right; +		else +			return (struct rb_node *)node; +	} +} + +struct rb_node *rb_next_postorder(const struct rb_node *node) +{ +	const struct rb_node *parent; +	if (!node) +		return NULL; +	parent = rb_parent(node); + +	/* If we're sitting on node, we've already seen our children */ +	if (parent && node == parent->rb_left && parent->rb_right) { +		/* If we are the parent's left node, go to the parent's right +		 * node then all the way down to the left */ +		return rb_left_deepest_node(parent->rb_right); +	} else +		/* Otherwise we are the parent's right node, and the parent +		 * should be next */ +		return (struct rb_node *)parent; +} +EXPORT_SYMBOL(rb_next_postorder); + +struct rb_node *rb_first_postorder(const struct rb_root *root) +{ +	if (!root->rb_node) +		return NULL; + +	return rb_left_deepest_node(root->rb_node); +} +EXPORT_SYMBOL(rb_first_postorder); | 
