|
1 Generic C code for red-black trees. |
|
2 Copyright (C) 2000 James S. Plank |
|
3 |
|
4 This library is free software; you can redistribute it and/or |
|
5 modify it under the terms of the GNU Lesser General Public |
|
6 License as published by the Free Software Foundation; either |
|
7 version 2.1 of the License, or (at your option) any later version. |
|
8 |
|
9 This library is distributed in the hope that it will be useful, |
|
10 but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
12 Lesser General Public License for more details. |
|
13 |
|
14 You should have received a copy of the GNU Lesser General Public |
|
15 License along with this library; if not, write to the Free Software |
|
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
17 |
|
18 --------------------------------------------------------------------------- |
|
19 Jim Plank |
|
20 plank@cs.utk.edu |
|
21 http://www.cs.utk.edu/~plank |
|
22 |
|
23 Department of Computer Science |
|
24 University of Tennessee |
|
25 107 Ayres Hall |
|
26 Knoxville, TN 37996 |
|
27 |
|
28 615-974-4397 |
|
29 $Revision: 1.2 $ |
|
30 --------------------------------------------------------------------------- |
|
31 |
|
32 Rb.c and rb.h are files for doing general red-black trees. |
|
33 |
|
34 The directory ansi contains ansi-standard c code for rb-trees (there |
|
35 are some gross pointer casts there but don't worry about them. They |
|
36 work). The directory non-ansi contains straight c code for rb-trees. |
|
37 The ansi version can also be used by c++ (it has been tested). |
|
38 |
|
39 Rb.h contains the typedef for red-black tree structures. Basically, |
|
40 red-black trees are balanced trees whose external nodes are sorted |
|
41 by a key, and connected in a linked list. The following is how |
|
42 you use rb.c and rb.h: |
|
43 |
|
44 Include rb.h in your source. |
|
45 |
|
46 Make_rb() returns the head of a red-black tree. It serves two functions: |
|
47 Its p.root pointer points to the root of the red-black tree. Its |
|
48 c.list.flink and c.list.blink pointers point to the first and last |
|
49 external nodes of the tree. When the tree is empty, all these pointers |
|
50 point to itself. |
|
51 |
|
52 The external nodes can be traversed in sorted order with their |
|
53 c.list.flink and c.list.blink pointers. The macros rb_first, rb_last, |
|
54 rb_next, rb_prev, and rb_traverse can be used to traverse external node lists. |
|
55 |
|
56 External nodes hold two pieces of information: the key and the value |
|
57 (in k.key and v.val, respectively). The key can be a character |
|
58 string, an integer, or a general pointer. Val is typed as a character |
|
59 pointer, but can be any pointer. If the key is a character string, |
|
60 then one can insert it, and a value into a tree with rb_insert(). If |
|
61 it is an integer, then rb_inserti() should be used. If it is a general |
|
62 pointer, then rb_insertg() must be used, with a comparison function |
|
63 passed as the fourth argument. This function takes two keys as arguments, |
|
64 and returns a negative value, positive value, or 0, depending on whether |
|
65 the first key is less than, greater than or equal to the second. Thus, |
|
66 one could use rb_insertg(t, s, v, strcmp) to insert the value v with |
|
67 a character string s into the tree t. |
|
68 |
|
69 Rb_find_key(t, k) returns the external node in t whose value is equal |
|
70 k or whose value is the smallest value greater than k. (Here, k is |
|
71 a string). If there is no value greater than or equal to k, then |
|
72 t is returned. Rb_find_ikey(t,k) works when k is an integer, and |
|
73 Rb_find_gkey(t,k,cmp) works for general pointers. |
|
74 |
|
75 Rb_find_key_n(t, k, n) is the same as rb_find_key, except that it |
|
76 returns whether or not k was found in n (n is an int *). Rb_find_ikey_n |
|
77 and Rb_find_gkey_n are the analogous routines for integer and general |
|
78 keys. |
|
79 |
|
80 Rb_insert_b(e, k, v) makes a new external node with key k and val v, and |
|
81 inserts it before the external node e. If e is the head of a tree, |
|
82 then the new node is inserted at the end of the external node list. |
|
83 If this insertion violates sorted order, no error is flagged. It is |
|
84 assumed that the user knows what he/she is doing. Rb_insert_a(e,k,v) |
|
85 inserts the new node after e (if e = t, it inserts the new node at the |
|
86 beginning of the list). |
|
87 |
|
88 Rb_insert() is therefore really a combination of Rb_find_key() and |
|
89 Rb_insert_b(). |
|
90 |
|
91 Rb_delete_node(e) deletes the external node e from a tree (and thus from |
|
92 the linked list of external nodes). The node is free'd as well, so |
|
93 don't retain pointers to it. |
|
94 |
|
95 Red-black trees are spiffy because find_key, insert, and delete are all |
|
96 done in log(n) time. Thus, they can be freely used instead of hash-tables, |
|
97 with the benifit of having the elements in sorted order at all times, and |
|
98 with the guarantee of operations being in log(n) time. |
|
99 |
|
100 Other routines: |
|
101 |
|
102 Rb_print_tree() will grossly print out a red-black tree with string keys. |
|
103 Rb_iprint_tree() will do the same with trees with integer keys. |
|
104 Rb_nblack(e) will report the number of black nodes on the path from external |
|
105 node e to the root. The path length is less than twice this value. |
|
106 Rb_plength(e) reports the length of the path from e to the root. |
|
107 |
|
108 |
|
109 You can find a general description of red-black trees in any basic algorithms |
|
110 text. E.g. ``Introduction to Algorithms'', by Cormen, Leiserson and Rivest |
|
111 (McGraw Hill). An excellent and complete description of red-black trees |
|
112 can also be found in Chapter 1 of Heather Booth's PhD disseratation: |
|
113 ``Some Fast Algorithms on Graphs and Trees'', Princeton University, 1990. |