linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
* AVL trees vs. Red-Black trees
@ 1999-11-27 12:59 Kevin O'Connor
  1999-11-28  2:57 ` Andrea Arcangeli
  0 siblings, 1 reply; 8+ messages in thread
From: Kevin O'Connor @ 1999-11-27 12:59 UTC (permalink / raw)
  To: linux-mm

Hi,

I've been spending the last few days "kicking around" different ideas for
implementing reusable data structures in C.  That is, generic hash tables,
linked lists, trees, etc.

I was planning on hacking up a kernel with a generic tree implementation.
(Right now there are two AVL trees in the kernel - one in the MM code and a
copy in the net/bridge code.)

I was a little surprised to see that the MM code uses an AVL tree - my old
textbooks are of the opinion that Red-Black trees are superior.
Implementing the code to create a stack for performing "bottom-up"
insertions/deletions seems like a pain to me.  I would think the "top-down"
approach of a Red-Black tree would be more efficient and probably simpler
to implement.

So my question is, was there a particular reason AVL trees were chosen, or
would any balanced tree implementation suffice?

-Kevin

-- 
 ------------------------------------------------------------------------
 | Kevin O'Connor                     "BTW, IMHO we need a FAQ for      |
 | koconnor@cse.buffalo.edu            'IMHO', 'FAQ', 'BTW', etc. !"    |
 ------------------------------------------------------------------------
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://humbolt.geo.uu.nl/Linux-MM/

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: AVL trees vs. Red-Black trees
  1999-11-27 12:59 AVL trees vs. Red-Black trees Kevin O'Connor
@ 1999-11-28  2:57 ` Andrea Arcangeli
  1999-11-28  5:29   ` Oliver Xymoron
  0 siblings, 1 reply; 8+ messages in thread
From: Andrea Arcangeli @ 1999-11-28  2:57 UTC (permalink / raw)
  To: Kevin O'Connor; +Cc: linux-mm, linux-kernel

On Sat, 27 Nov 1999, Kevin O'Connor wrote:

>I was a little surprised to see that the MM code uses an AVL tree - my old
>textbooks are of the opinion that Red-Black trees are superior.

You basically do a query for each page fault and an insert for each mmap
and a remove for each munmap thus AVL gives better performances.

>Implementing the code to create a stack for performing "bottom-up"
>insertions/deletions seems like a pain to me.  I would think the "top-down"
>approach of a Red-Black tree would be more efficient and probably simpler
>to implement.

I just implemented RB trees in the kernel with a reusable implementation
exactly like include/linux/list.h for the lists.

If somebody find this interesting I can provide a patch to add the
include/linux/rbtree.h and lib/rbtree.c that will provde rbtree support.

Andrea

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://humbolt.geo.uu.nl/Linux-MM/

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: AVL trees vs. Red-Black trees
  1999-11-28  2:57 ` Andrea Arcangeli
@ 1999-11-28  5:29   ` Oliver Xymoron
  1999-11-29 15:54     ` [patch] rbtrees [was Re: AVL trees vs. Red-Black trees] Andrea Arcangeli
  0 siblings, 1 reply; 8+ messages in thread
From: Oliver Xymoron @ 1999-11-28  5:29 UTC (permalink / raw)
  To: Andrea Arcangeli; +Cc: Kevin O'Connor, linux-mm, linux-kernel

On Sun, 28 Nov 1999, Andrea Arcangeli wrote:

> On Sat, 27 Nov 1999, Kevin O'Connor wrote:
> 
> >I was a little surprised to see that the MM code uses an AVL tree - my old
> >textbooks are of the opinion that Red-Black trees are superior.
> 
> You basically do a query for each page fault and an insert for each mmap
> and a remove for each munmap thus AVL gives better performances.
> 
> >Implementing the code to create a stack for performing "bottom-up"
> >insertions/deletions seems like a pain to me.  I would think the "top-down"
> >approach of a Red-Black tree would be more efficient and probably simpler
> >to implement.
> 
> I just implemented RB trees in the kernel with a reusable implementation
> exactly like include/linux/list.h for the lists.
> 
> If somebody find this interesting I can provide a patch to add the
> include/linux/rbtree.h and lib/rbtree.c that will provde rbtree support.

I'd like to take a look at this, I've been looking at putting some more
uniform tree structures in the kernel (post 2.4).

--
 "Love the dolphins," she advised him. "Write by W.A.S.T.E.." 

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://humbolt.geo.uu.nl/Linux-MM/

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [patch] rbtrees [was Re: AVL trees vs. Red-Black trees]
  1999-11-28  5:29   ` Oliver Xymoron
@ 1999-11-29 15:54     ` Andrea Arcangeli
  1999-11-29 19:18       ` Manfred Spraul
  0 siblings, 1 reply; 8+ messages in thread
From: Andrea Arcangeli @ 1999-11-29 15:54 UTC (permalink / raw)
  To: Oliver Xymoron
  Cc: Kevin O'Connor, linux-mm, linux-kernel, Marc Lehmann, Linus Torvalds

On Sat, 27 Nov 1999, Oliver Xymoron wrote:

>I'd like to take a look at this, I've been looking at putting some more
>uniform tree structures in the kernel (post 2.4).

This patch will add btree support to linux. I extracted it from my old
patches. I think it could be added also in the stock kernel so if somebody
needs rbtrees, he won't have to reinvent the wheel each time ;). The patch
is against 2.3.30pre3.

diff -urN 2.3.30pre3/include/linux/rbtree.h 2.3.30pre3-rbtree/include/linux/rbtree.h
--- 2.3.30pre3/include/linux/rbtree.h	Thu Jan  1 01:00:00 1970
+++ 2.3.30pre3-rbtree/include/linux/rbtree.h	Mon Nov 29 16:33:26 1999
@@ -0,0 +1,128 @@
+/*
+  Red Black Trees
+  (C) 1999  Andrea Arcangeli <andrea@suse.de>
+  
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  linux/include/linux/rbtree.h
+
+  To use rbtrees you'll have to implement your own insert and search cores.
+  This will avoid us to use callbacks and to drop drammatically performances.
+  I know it's not the cleaner way,  but in C (not in C++) to get
+  performances and genericity...
+
+  Some example of insert and search follows here. The search is a plain
+  normal search over an ordered tree. The insert instead must be implemented
+  int two steps: as first thing the code must insert the element in
+  order as a red leaf in the tree, then the support library function
+  rb_insert_color() must be called. Such function will do the
+  not trivial work to rebalance the rbtree if necessary.
+
+-----------------------------------------------------------------------
+static inline struct page * rb_search_page_cache(struct inode * inode,
+						 unsigned long offset)
+{
+	rb_node_t * n = inode->i_rb_page_cache.rb_node;
+	struct page * page;
+
+	while (n)
+	{
+		page = rb_entry(n, struct page, rb_page_cache);
+
+		if (offset < page->offset)
+			n = n->rb_left;
+		else if (offset > page->offset)
+			n = n->rb_right;
+		else
+			return page;
+	}
+	return NULL;
+}
+
+static inline struct page * __rb_insert_page_cache(struct inode * inode,
+						   unsigned long offset,
+						   rb_node_t * node)
+{
+	rb_node_t ** p = &inode->i_rb_page_cache.rb_node;
+	rb_node_t * parent = NULL;
+	struct page * page;
+
+	while (*p)
+	{
+		parent = *p;
+		page = rb_entry(parent, struct page, rb_page_cache);
+
+		if (offset < page->offset)
+			p = &(*p)->rb_left;
+		else if (offset > page->offset)
+			p = &(*p)->rb_right;
+		else
+			return page;
+	}
+
+	node->rb_parent = parent;
+	node->rb_color = RB_RED;
+	node->rb_left = node->rb_right = NULL;
+
+	*p = node;
+
+	return NULL;
+}
+
+static inline struct page * rb_insert_page_cache(struct inode * inode,
+						 unsigned long offset,
+						 rb_node_t * node)
+{
+	struct page * ret;
+	if ((ret = __rb_insert_page_cache(inode, offset, node)))
+		goto out;
+	rb_insert_color(node, &inode->i_rb_page_cache);
+ out:
+	return ret;
+}
+-----------------------------------------------------------------------
+*/
+
+#ifndef	_LINUX_RBTREE_H
+#define	_LINUX_RBTREE_H
+
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+
+typedef struct rb_node_s
+{
+	struct rb_node_s * rb_parent;
+	int rb_color;
+#define	RB_RED		0
+#define	RB_BLACK	1
+	struct rb_node_s * rb_right;
+	struct rb_node_s * rb_left;
+}
+rb_node_t;
+
+typedef struct rb_root_s
+{
+	struct rb_node_s * rb_node;
+}
+rb_root_t;
+
+#define RB_ROOT	(rb_root_t) { NULL, }
+#define	rb_entry(ptr, type, member)					\
+	((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
+
+extern void rb_insert_color(rb_node_t *, rb_root_t *);
+extern void rb_erase(rb_node_t *, rb_root_t *);
+
+#endif	/* _LINUX_RBTREE_H */
diff -urN 2.3.30pre3/lib/Makefile 2.3.30pre3-rbtree/lib/Makefile
--- 2.3.30pre3/lib/Makefile	Mon Jan 18 02:27:00 1999
+++ 2.3.30pre3-rbtree/lib/Makefile	Mon Nov 29 16:22:36 1999
@@ -7,6 +7,6 @@
 #
 
 L_TARGET := lib.a
-L_OBJS   := errno.o ctype.o string.o vsprintf.o
+L_OBJS   := errno.o ctype.o string.o vsprintf.o rbtree.o
 
 include $(TOPDIR)/Rules.make
diff -urN 2.3.30pre3/lib/rbtree.c 2.3.30pre3-rbtree/lib/rbtree.c
--- 2.3.30pre3/lib/rbtree.c	Thu Jan  1 01:00:00 1970
+++ 2.3.30pre3-rbtree/lib/rbtree.c	Mon Nov 29 16:31:37 1999
@@ -0,0 +1,293 @@
+/*
+  Red Black Trees
+  (C) 1999  Andrea Arcangeli <andrea@suse.de>
+  
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+  linux/lib/rbtree.c
+*/
+
+#include <linux/rbtree.h>
+
+static void __rb_rotate_left(rb_node_t * node, rb_root_t * root)
+{
+	rb_node_t * right = node->rb_right;
+
+	if ((node->rb_right = right->rb_left))
+		right->rb_left->rb_parent = node;
+	right->rb_left = node;
+
+	if ((right->rb_parent = node->rb_parent))
+	{
+		if (node == node->rb_parent->rb_left)
+			node->rb_parent->rb_left = right;
+		else
+			node->rb_parent->rb_right = right;
+	}
+	else
+		root->rb_node = right;
+	node->rb_parent = right;
+}
+
+static void __rb_rotate_right(rb_node_t * node, rb_root_t * root)
+{
+	rb_node_t * left = node->rb_left;
+
+	if ((node->rb_left = left->rb_right))
+		left->rb_right->rb_parent = node;
+	left->rb_right = node;
+
+	if ((left->rb_parent = node->rb_parent))
+	{
+		if (node == node->rb_parent->rb_right)
+			node->rb_parent->rb_right = left;
+		else
+			node->rb_parent->rb_left = left;
+	}
+	else
+		root->rb_node = left;
+	node->rb_parent = left;
+}
+
+void rb_insert_color(rb_node_t * node, rb_root_t * root)
+{
+	rb_node_t * parent, * gparent;
+
+	while ((parent = node->rb_parent) && parent->rb_color == RB_RED)
+	{
+		gparent = parent->rb_parent;
+
+		if (parent == gparent->rb_left)
+		{
+			{
+				register rb_node_t * uncle = gparent->rb_right;
+				if (uncle && uncle->rb_color == RB_RED)
+				{
+					uncle->rb_color = RB_BLACK;
+					parent->rb_color = RB_BLACK;
+					gparent->rb_color = RB_RED;
+					node = gparent;
+					continue;
+				}
+			}
+
+			if (parent->rb_right == node)
+			{
+				register rb_node_t * tmp;
+				__rb_rotate_left(parent, root);
+				tmp = parent;
+				parent = node;
+				node = tmp;
+			}
+
+			parent->rb_color = RB_BLACK;
+			gparent->rb_color = RB_RED;
+			__rb_rotate_right(gparent, root);
+		} else {
+			{
+				register rb_node_t * uncle = gparent->rb_left;
+				if (uncle && uncle->rb_color == RB_RED)
+				{
+					uncle->rb_color = RB_BLACK;
+					parent->rb_color = RB_BLACK;
+					gparent->rb_color = RB_RED;
+					node = gparent;
+					continue;
+				}
+			}
+
+			if (parent->rb_left == node)
+			{
+				register rb_node_t * tmp;
+				__rb_rotate_right(parent, root);
+				tmp = parent;
+				parent = node;
+				node = tmp;
+			}
+
+			parent->rb_color = RB_BLACK;
+			gparent->rb_color = RB_RED;
+			__rb_rotate_left(gparent, root);
+		}
+	}
+
+	root->rb_node->rb_color = RB_BLACK;
+}
+
+static void __rb_erase_color(rb_node_t * node, rb_node_t * parent,
+			     rb_root_t * root)
+{
+	rb_node_t * other;
+
+	while ((!node || node->rb_color == RB_BLACK) && node != root->rb_node)
+	{
+		if (parent->rb_left == node)
+		{
+			other = parent->rb_right;
+			if (other->rb_color == RB_RED)
+			{
+				other->rb_color = RB_BLACK;
+				parent->rb_color = RB_RED;
+				__rb_rotate_left(parent, root);
+				other = parent->rb_right;
+			}
+			if ((!other->rb_left ||
+			     other->rb_left->rb_color == RB_BLACK)
+			    && (!other->rb_right ||
+				other->rb_right->rb_color == RB_BLACK))
+			{
+				other->rb_color = RB_RED;
+				node = parent;
+				parent = node->rb_parent;
+			}
+			else
+			{
+				if (!other->rb_right ||
+				    other->rb_right->rb_color == RB_BLACK)
+				{
+					register rb_node_t * o_left;
+					if ((o_left = other->rb_left))
+						o_left->rb_color = RB_BLACK;
+					other->rb_color = RB_RED;
+					__rb_rotate_right(other, root);
+					other = parent->rb_right;
+				}
+				other->rb_color = parent->rb_color;
+				parent->rb_color = RB_BLACK;
+				if (other->rb_right)
+					other->rb_right->rb_color = RB_BLACK;
+				__rb_rotate_left(parent, root);
+				node = root->rb_node;
+				break;
+			}
+		}
+		else
+		{
+			other = parent->rb_left;
+			if (other->rb_color == RB_RED)
+			{
+				other->rb_color = RB_BLACK;
+				parent->rb_color = RB_RED;
+				__rb_rotate_right(parent, root);
+				other = parent->rb_left;
+			}
+			if ((!other->rb_left ||
+			     other->rb_left->rb_color == RB_BLACK)
+			    && (!other->rb_right ||
+				other->rb_right->rb_color == RB_BLACK))
+			{
+				other->rb_color = RB_RED;
+				node = parent;
+				parent = node->rb_parent;
+			}
+			else
+			{
+				if (!other->rb_left ||
+				    other->rb_left->rb_color == RB_BLACK)
+				{
+					register rb_node_t * o_right;
+					if ((o_right = other->rb_right))
+						o_right->rb_color = RB_BLACK;
+					other->rb_color = RB_RED;
+					__rb_rotate_left(other, root);
+					other = parent->rb_left;
+				}
+				other->rb_color = parent->rb_color;
+				parent->rb_color = RB_BLACK;
+				if (other->rb_left)
+					other->rb_left->rb_color = RB_BLACK;
+				__rb_rotate_right(parent, root);
+				node = root->rb_node;
+				break;
+			}
+		}
+	}
+	if (node)
+		node->rb_color = RB_BLACK;
+}
+
+void rb_erase(rb_node_t * node, rb_root_t * root)
+{
+	rb_node_t * child, * parent;
+	int color;
+
+	if (!node->rb_left)
+		child = node->rb_right;
+	else if (!node->rb_right)
+		child = node->rb_left;
+	else
+	{
+		rb_node_t * old = node, * left;
+
+		node = node->rb_right;
+		while ((left = node->rb_left))
+			node = left;
+		child = node->rb_right;
+		parent = node->rb_parent;
+		color = node->rb_color;
+
+		if (child)
+			child->rb_parent = parent;
+		if (parent)
+		{
+			if (parent->rb_left == node)
+				parent->rb_left = child;
+			else
+				parent->rb_right = child;
+		}
+		else
+			root->rb_node = child;
+
+		if (node->rb_parent == old)
+			parent = node;
+		node->rb_parent = old->rb_parent;
+		node->rb_color = old->rb_color;
+		node->rb_right = old->rb_right;
+		node->rb_left = old->rb_left;
+
+		if (old->rb_parent)
+		{
+			if (old->rb_parent->rb_left == old)
+				old->rb_parent->rb_left = node;
+			else
+				old->rb_parent->rb_right = node;
+		} else
+			root->rb_node = node;
+
+		old->rb_left->rb_parent = node;
+		if (old->rb_right)
+			old->rb_right->rb_parent = node;
+		goto color;
+	}
+
+	parent = node->rb_parent;
+	color = node->rb_color;
+
+	if (child)
+		child->rb_parent = parent;
+	if (parent)
+	{
+		if (parent->rb_left == node)
+			parent->rb_left = child;
+		else
+			parent->rb_right = child;
+	}
+	else
+		root->rb_node = child;
+
+ color:
+	if (color == RB_BLACK)
+		__rb_erase_color(child, parent, root);
+}


Downloadable also from:

	ftp://ftp.*.kernel.org/pub/linux/kernel/people/andrea/patches/v2.3/2.3.30pre3/rbtree-1.bz2

Andrea

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://humbolt.geo.uu.nl/Linux-MM/

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [patch] rbtrees [was Re: AVL trees vs. Red-Black trees]
  1999-11-29 19:18       ` Manfred Spraul
@ 1999-11-29 19:17         ` Andrea Arcangeli
  1999-11-30  5:27         ` Kevin O'Connor
  1 sibling, 0 replies; 8+ messages in thread
From: Andrea Arcangeli @ 1999-11-29 19:17 UTC (permalink / raw)
  To: Manfred Spraul
  Cc: Oliver Xymoron, Kevin O'Connor, linux-mm, linux-kernel,
	Marc Lehmann, Linus Torvalds

On Mon, 29 Nov 1999, Manfred Spraul wrote:

>What about something similar to the "end_request()" implementation?

Personally I don't cosider that very nicer. Also look at what I am doing
in the insert, my insert also does a query, you may also do differnet
things.

But if you think it worth, I can implement that of course.

Andrea

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://humbolt.geo.uu.nl/Linux-MM/

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [patch] rbtrees [was Re: AVL trees vs. Red-Black trees]
  1999-11-29 15:54     ` [patch] rbtrees [was Re: AVL trees vs. Red-Black trees] Andrea Arcangeli
@ 1999-11-29 19:18       ` Manfred Spraul
  1999-11-29 19:17         ` Andrea Arcangeli
  1999-11-30  5:27         ` Kevin O'Connor
  0 siblings, 2 replies; 8+ messages in thread
From: Manfred Spraul @ 1999-11-29 19:18 UTC (permalink / raw)
  To: Andrea Arcangeli
  Cc: Oliver Xymoron, Kevin O'Connor, linux-mm, linux-kernel,
	Marc Lehmann, Linus Torvalds

Andrea Arcangeli wrote:
> +  To use rbtrees you'll have to implement your own insert and search cores.
> +  This will avoid us to use callbacks and to drop drammatically performances.
> +  I know it's not the cleaner way,  but in C (not in C++) to get
> +  performances and genericity...
> +
> +  Some example of insert and search follows here. The search is a plain
> +  normal search over an ordered tree. The insert instead must be implemented
> +  int two steps: as first thing the code must insert the element in
> +  order as a red leaf in the tree, then the support library function
> +  rb_insert_color() must be called. Such function will do the
> +  not trivial work to rebalance the rbtree if necessary.

What about something similar to the "end_request()" implementation?

ie you #define a name and the (inline) compare function, then you
#include <rbtree.h>. <rbtree.h> creates all functions that you need.

--
	Manfred
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://humbolt.geo.uu.nl/Linux-MM/

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [patch] rbtrees [was Re: AVL trees vs. Red-Black trees]
  1999-11-29 19:18       ` Manfred Spraul
  1999-11-29 19:17         ` Andrea Arcangeli
@ 1999-11-30  5:27         ` Kevin O'Connor
  1999-11-30 14:14           ` Andrea Arcangeli
  1 sibling, 1 reply; 8+ messages in thread
From: Kevin O'Connor @ 1999-11-30  5:27 UTC (permalink / raw)
  To: Manfred Spraul
  Cc: Andrea Arcangeli, Oliver Xymoron, Kevin O'Connor, linux-mm,
	linux-kernel, Marc Lehmann, Linus Torvalds

On Mon, Nov 29, 1999 at 08:18:17PM +0100, Manfred Spraul wrote:
> What about something similar to the "end_request()" implementation?
> 
> ie you #define a name and the (inline) compare function, then you
> #include <rbtree.h>. <rbtree.h> creates all functions that you need.

I don't much like this method - IMO, it obfuscates the #include directive.
That said, however, I implemented a generic AVL tree implementation using a
similar idea.  Basically, I define a couple of MACROs: AVL_FIND and
AVL_FINDWITHSTACK (needed by AVL trees to do a bottom-up insert/delete).
These macros take a compare function as a parameter.  If the compare
function is declared as inline, or if it is a macro, it will be compiled
inline and without the overhead of a call instruction.

I'm including a sample usage, plus an excerpt from my avltree.h header file
- just to give a sample of how I would implement generic trees.

I can provide more code upon request.  I've got inserts working, but
removes are becoming a myriad of special cases..

Note: I tried to be "clever", and store the tree height in the low-order
bytes of a pointer.  It works, but it's pretty ugly.

-Kevin

=============  Sample application usage ===============

struct hrmm {
	int num;
	avl_node_t treenode;
};

static inline int
mycmp(avl_node_t *x, avl_node_t *y)
{
	int a,b;

	a = avl_entry(x, struct hrmm, treenode)->num;
	b = avl_entry(y, struct hrmm, treenode)->num;

	return (a < b ? -1 : a > b ? 1 : 0);
}

int
my_insert(avl_node_t **tree, struct hrmm *node)
{
	return AVL_INSERT(tree,&node->treenode,mycmp);
}

int
my_remove(avl_node_t **tree, struct hrmm *node)
{
	return AVL_REMOVE(tree,&node->treenode,mycmp);
}

struct hrmm *
my_find(avl_node_t *tree, struct hrmm *node)
{
	return avl_entry(AVL_FIND(tree,&node->treenode,mycmp)
			 , struct hrmm, treenode);
}

=============  Macros from header file  ===============

#define AVL_FIND(__Tree,__Node,__Compare) ({			\
	avl_node_t *__tree = (__Tree);				\
								\
	while (__tree) {					\
		int __compval = __Compare((__Node),__tree);	\
								\
		if (__compval < 0) {				\
			__tree = getChild(__tree, TREE_LEFT);	\
		} else if (__compval > 0) {			\
			__tree = getChild(__tree, TREE_RIGHT);	\
		} else {					\
			break;					\
		}						\
	}							\
	__tree;})

#define AVL_FINDWITHSTACK(__TreeP,__Node,__Stack,__Count,__Compare) ({	\
	avl_node_t **__tree = (__TreeP), *__tmp;		  	\
	avl_dptr_t *__stack = (__Stack);			     	\
	int *__count = (__Count), __found=0;			     	\
								     	\
	__tmp = *__tree;					     	\
	*__count = 0;						     	\
	__stack[0] = (avl_dptr_t) __tree;			     	\
	while (__tmp) {						     	\
		int __compval = __Compare((__Node), __tmp);	     	\
								     	\
		if (__compval < 0) {				     	\
			(*__count)++;				     	\
			setPtr(&__stack[*__count], __tmp, TREE_LEFT);   \
			__tmp = getChild(__tmp, TREE_LEFT);	     	\
		} else if (__compval > 0) {			     	\
			(*__count)++;				     	\
			setPtr(&__stack[*__count], __tmp, TREE_RIGHT);  \
			__tmp = getChild(__tmp, TREE_RIGHT);	     	\
		} else {					     	\
			__found = 1;				     	\
			break;					     	\
		}						     	\
	}							     	\
	__found;})

#define AVL_REMOVE(__TreeP,__Node,__Compare) ({			\
	avl_dptr_t __stk[AVL_MAXHEIGHT];			\
	int __cnt, __ret;					\
								\
	if (! AVL_FINDWITHSTACK((__TreeP),(__Node)		\
				,__stk,&__cnt,__Compare)) {	\
		__ret = 0;					\
	} else {						\
		avl_remove(__stk, __cnt);			\
		__ret = 1;					\
	}							\
	__ret;})

#define AVL_INSERT(__TreeP,__Node,__Compare) ({			\
	avl_dptr_t __stk[AVL_MAXHEIGHT];			\
	int __cnt, __ret;					\
								\
	if (AVL_FINDWITHSTACK((__TreeP),(__Node)		\
				,__stk,&__cnt,__Compare)) {	\
		__ret = 0;					\
	} else {						\
		avl_insert((__Node), __stk, __cnt);		\
		__ret = 1;					\
	}							\
	__ret;})



-- 
 ------------------------------------------------------------------------
 | Kevin O'Connor                     "BTW, IMHO we need a FAQ for      |
 | koconnor@cse.buffalo.edu            'IMHO', 'FAQ', 'BTW', etc. !"    |
 ------------------------------------------------------------------------
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://humbolt.geo.uu.nl/Linux-MM/

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [patch] rbtrees [was Re: AVL trees vs. Red-Black trees]
  1999-11-30  5:27         ` Kevin O'Connor
@ 1999-11-30 14:14           ` Andrea Arcangeli
  0 siblings, 0 replies; 8+ messages in thread
From: Andrea Arcangeli @ 1999-11-30 14:14 UTC (permalink / raw)
  To: Kevin O'Connor
  Cc: Manfred Spraul, Oliver Xymoron, linux-mm, linux-kernel,
	Marc Lehmann, Linus Torvalds

On Tue, 30 Nov 1999, Kevin O'Connor wrote:

>[..]  I've got inserts working, but
>removes are becoming a myriad of special cases..

removes are trivial with rbtrees as you never need to compare nodes. All
the rebalancing is done in function of the node color (that is a private
information of each node). The same is true also for the
insert-rebalancing, but to do an insert you must first browse the tree to
do a normal ordered O(log(n)) insert before calling the rebalance (thus a
compare semantic on elements is necessary for the insert operation to
work).

Andrea




--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://humbolt.geo.uu.nl/Linux-MM/

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~1999-11-30 14:14 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1999-11-27 12:59 AVL trees vs. Red-Black trees Kevin O'Connor
1999-11-28  2:57 ` Andrea Arcangeli
1999-11-28  5:29   ` Oliver Xymoron
1999-11-29 15:54     ` [patch] rbtrees [was Re: AVL trees vs. Red-Black trees] Andrea Arcangeli
1999-11-29 19:18       ` Manfred Spraul
1999-11-29 19:17         ` Andrea Arcangeli
1999-11-30  5:27         ` Kevin O'Connor
1999-11-30 14:14           ` Andrea Arcangeli

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox