Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
Nadezhda Ivanova
OpenLDAP
Commits
2c21fdce
Commit
2c21fdce
authored
Nov 26, 2003
by
Kurt Zeilenga
Browse files
move AVL routines into -llutil
update misc notices
parent
a6bc7469
Changes
29
Hide whitespace changes
Inline
Side-by-side
include/portable.h.in
View file @
2c21fdce
/* include/portable.h.in. Generated automatically from configure.in by autoheader. */
/* Copyright 1998-2003 The OpenLDAP Foundation
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 1998-2003 The OpenLDAP Foundation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
...
...
libraries/Makefile.in
View file @
2c21fdce
# Libraries Makefile for OpenLDAP
# $OpenLDAP$
## This work is part of OpenLDAP Software <http://www.openldap.org/>.
##
## Copyright 1998-2003 The OpenLDAP Foundation.
## All rights reserved.
##
...
...
@@ -16,7 +18,6 @@ SUBDIRS= \
liblber
\
liblunicode
\
libldap libldap_r
\
libavl
\
libldbm
\
librewrite
libraries/libavl/Makefile.in
deleted
100644 → 0
View file @
a6bc7469
# LIBAVL
# $OpenLDAP$
## Copyright 1998-2003 The OpenLDAP Foundation.
## All rights reserved.
##
## Redistribution and use in source and binary forms, with or without
## modification, are permitted only as authorized by the OpenLDAP
## Public License.
##
## A copy of this license is available in the file LICENSE in the
## top-level directory of the distribution or, alternatively, at
## <http://www.OpenLDAP.org/license.html>.
SRCS
=
avl.c testavl.c
XSRCS
=
version.c
OBJS
=
avl.o
LDAP_INCDIR
=
../../include
LDAP_LIBDIR
=
../../libraries
LIBRARY
=
libavl.a
PROGRAMS
=
testavl
XLIBS
=
$(LIBRARY)
$(LDAP_LIBLBER_LA)
$(LDAP_LIBLUTIL_A)
testavl
:
$(XLIBS) testavl.o
$(LTLINK)
-o
$@
testavl.o
$(LIBS)
libraries/libavl/avl.c
deleted
100644 → 0
View file @
a6bc7469
/* avl.c - routines to implement an avl tree */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 1998-2003 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/* Portions Copyright (c) 1993 Regents of the University of Michigan.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that this notice is preserved and that due credit is given
* to the University of Michigan at Ann Arbor. The name of the University
* may not be used to endorse or promote products derived from this
* software without specific prior written permission. This software
* is provided ``as is'' without express or implied warranty.
*/
/* This work was originally developed by the University of Michigan
* (as part of U-MICH LDAP).
*/
#include
"portable.h"
#include
<stdio.h>
#include
<ac/stdlib.h>
#ifdef CSRIMALLOC
#define ber_memalloc malloc
#define ber_memrealloc realloc
#define ber_memfree free
#else
#include
"lber.h"
#endif
#define AVL_INTERNAL
#include
"avl.h"
#define ROTATERIGHT(x) { \
Avlnode *tmp;\
if ( *(x) == NULL || (*(x))->avl_left == NULL ) {\
(void) fputs("RR error\n", stderr); exit( EXIT_FAILURE ); \
}\
tmp = (*(x))->avl_left;\
(*(x))->avl_left = tmp->avl_right;\
tmp->avl_right = *(x);\
*(x) = tmp;\
}
#define ROTATELEFT(x) { \
Avlnode *tmp;\
if ( *(x) == NULL || (*(x))->avl_right == NULL ) {\
(void) fputs("RL error\n", stderr); exit( EXIT_FAILURE ); \
}\
tmp = (*(x))->avl_right;\
(*(x))->avl_right = tmp->avl_left;\
tmp->avl_left = *(x);\
*(x) = tmp;\
}
/*
* ravl_insert - called from avl_insert() to do a recursive insert into
* and balance of an avl tree.
*/
static
int
ravl_insert
(
Avlnode
**
iroot
,
void
*
data
,
int
*
taller
,
AVL_CMP
fcmp
,
/* comparison function */
AVL_DUP
fdup
,
/* function to call for duplicates */
int
depth
)
{
int
rc
,
cmp
,
tallersub
;
Avlnode
*
l
,
*
r
;
if
(
*
iroot
==
0
)
{
if
(
(
*
iroot
=
(
Avlnode
*
)
ber_memalloc
(
sizeof
(
Avlnode
)
))
==
NULL
)
{
return
(
-
1
);
}
(
*
iroot
)
->
avl_left
=
0
;
(
*
iroot
)
->
avl_right
=
0
;
(
*
iroot
)
->
avl_bf
=
0
;
(
*
iroot
)
->
avl_data
=
data
;
*
taller
=
1
;
return
(
0
);
}
cmp
=
(
*
fcmp
)(
data
,
(
*
iroot
)
->
avl_data
);
/* equal - duplicate name */
if
(
cmp
==
0
)
{
*
taller
=
0
;
return
(
(
*
fdup
)(
(
*
iroot
)
->
avl_data
,
data
)
);
}
/* go right */
else
if
(
cmp
>
0
)
{
rc
=
ravl_insert
(
&
((
*
iroot
)
->
avl_right
),
data
,
&
tallersub
,
fcmp
,
fdup
,
depth
);
if
(
tallersub
)
switch
(
(
*
iroot
)
->
avl_bf
)
{
case
LH
:
/* left high - balance is restored */
(
*
iroot
)
->
avl_bf
=
EH
;
*
taller
=
0
;
break
;
case
EH
:
/* equal height - now right heavy */
(
*
iroot
)
->
avl_bf
=
RH
;
*
taller
=
1
;
break
;
case
RH
:
/* right heavy to start - right balance */
r
=
(
*
iroot
)
->
avl_right
;
switch
(
r
->
avl_bf
)
{
case
LH
:
/* double rotation left */
l
=
r
->
avl_left
;
switch
(
l
->
avl_bf
)
{
case
LH
:
(
*
iroot
)
->
avl_bf
=
EH
;
r
->
avl_bf
=
RH
;
break
;
case
EH
:
(
*
iroot
)
->
avl_bf
=
EH
;
r
->
avl_bf
=
EH
;
break
;
case
RH
:
(
*
iroot
)
->
avl_bf
=
LH
;
r
->
avl_bf
=
EH
;
break
;
}
l
->
avl_bf
=
EH
;
ROTATERIGHT
(
(
&
r
)
)
(
*
iroot
)
->
avl_right
=
r
;
ROTATELEFT
(
iroot
)
*
taller
=
0
;
break
;
case
EH
:
/* This should never happen */
break
;
case
RH
:
/* single rotation left */
(
*
iroot
)
->
avl_bf
=
EH
;
r
->
avl_bf
=
EH
;
ROTATELEFT
(
iroot
)
*
taller
=
0
;
break
;
}
break
;
}
else
*
taller
=
0
;
}
/* go left */
else
{
rc
=
ravl_insert
(
&
((
*
iroot
)
->
avl_left
),
data
,
&
tallersub
,
fcmp
,
fdup
,
depth
);
if
(
tallersub
)
switch
(
(
*
iroot
)
->
avl_bf
)
{
case
LH
:
/* left high to start - left balance */
l
=
(
*
iroot
)
->
avl_left
;
switch
(
l
->
avl_bf
)
{
case
LH
:
/* single rotation right */
(
*
iroot
)
->
avl_bf
=
EH
;
l
->
avl_bf
=
EH
;
ROTATERIGHT
(
iroot
)
*
taller
=
0
;
break
;
case
EH
:
/* this should never happen */
break
;
case
RH
:
/* double rotation right */
r
=
l
->
avl_right
;
switch
(
r
->
avl_bf
)
{
case
LH
:
(
*
iroot
)
->
avl_bf
=
RH
;
l
->
avl_bf
=
EH
;
break
;
case
EH
:
(
*
iroot
)
->
avl_bf
=
EH
;
l
->
avl_bf
=
EH
;
break
;
case
RH
:
(
*
iroot
)
->
avl_bf
=
EH
;
l
->
avl_bf
=
LH
;
break
;
}
r
->
avl_bf
=
EH
;
ROTATELEFT
(
(
&
l
)
)
(
*
iroot
)
->
avl_left
=
l
;
ROTATERIGHT
(
iroot
)
*
taller
=
0
;
break
;
}
break
;
case
EH
:
/* equal height - now left heavy */
(
*
iroot
)
->
avl_bf
=
LH
;
*
taller
=
1
;
break
;
case
RH
:
/* right high - balance is restored */
(
*
iroot
)
->
avl_bf
=
EH
;
*
taller
=
0
;
break
;
}
else
*
taller
=
0
;
}
return
(
rc
);
}
/*
* avl_insert -- insert a node containing data data into the avl tree
* with root root. fcmp is a function to call to compare the data portion
* of two nodes. it should take two arguments and return <, >, or == 0,
* depending on whether its first argument is <, >, or == its second
* argument (like strcmp, e.g.). fdup is a function to call when a duplicate
* node is inserted. it should return 0, or -1 and its return value
* will be the return value from avl_insert in the case of a duplicate node.
* the function will be called with the original node's data as its first
* argument and with the incoming duplicate node's data as its second
* argument. this could be used, for example, to keep a count with each
* node.
*
* NOTE: this routine may malloc memory
*/
int
avl_insert
(
Avlnode
**
root
,
void
*
data
,
AVL_CMP
fcmp
,
AVL_DUP
fdup
)
{
int
taller
;
return
(
ravl_insert
(
root
,
data
,
&
taller
,
fcmp
,
fdup
,
0
)
);
}
/*
* right_balance() - called from delete when root's right subtree has
* been shortened because of a deletion.
*/
static
int
right_balance
(
Avlnode
**
root
)
{
int
shorter
=
-
1
;
Avlnode
*
r
,
*
l
;
switch
(
(
*
root
)
->
avl_bf
)
{
case
RH
:
/* was right high - equal now */
(
*
root
)
->
avl_bf
=
EH
;
shorter
=
1
;
break
;
case
EH
:
/* was equal - left high now */
(
*
root
)
->
avl_bf
=
LH
;
shorter
=
0
;
break
;
case
LH
:
/* was right high - balance */
l
=
(
*
root
)
->
avl_left
;
switch
(
l
->
avl_bf
)
{
case
RH
:
/* double rotation left */
r
=
l
->
avl_right
;
switch
(
r
->
avl_bf
)
{
case
RH
:
(
*
root
)
->
avl_bf
=
EH
;
l
->
avl_bf
=
LH
;
break
;
case
EH
:
(
*
root
)
->
avl_bf
=
EH
;
l
->
avl_bf
=
EH
;
break
;
case
LH
:
(
*
root
)
->
avl_bf
=
RH
;
l
->
avl_bf
=
EH
;
break
;
}
r
->
avl_bf
=
EH
;
ROTATELEFT
(
(
&
l
)
)
(
*
root
)
->
avl_left
=
l
;
ROTATERIGHT
(
root
)
shorter
=
1
;
break
;
case
EH
:
/* right rotation */
(
*
root
)
->
avl_bf
=
LH
;
l
->
avl_bf
=
RH
;
ROTATERIGHT
(
root
);
shorter
=
0
;
break
;
case
LH
:
/* single rotation right */
(
*
root
)
->
avl_bf
=
EH
;
l
->
avl_bf
=
EH
;
ROTATERIGHT
(
root
)
shorter
=
1
;
break
;
}
break
;
}
return
(
shorter
);
}
/*
* left_balance() - called from delete when root's left subtree has
* been shortened because of a deletion.
*/
static
int
left_balance
(
Avlnode
**
root
)
{
int
shorter
=
-
1
;
Avlnode
*
r
,
*
l
;
switch
(
(
*
root
)
->
avl_bf
)
{
case
LH
:
/* was left high - equal now */
(
*
root
)
->
avl_bf
=
EH
;
shorter
=
1
;
break
;
case
EH
:
/* was equal - right high now */
(
*
root
)
->
avl_bf
=
RH
;
shorter
=
0
;
break
;
case
RH
:
/* was right high - balance */
r
=
(
*
root
)
->
avl_right
;
switch
(
r
->
avl_bf
)
{
case
LH
:
/* double rotation left */
l
=
r
->
avl_left
;
switch
(
l
->
avl_bf
)
{
case
LH
:
(
*
root
)
->
avl_bf
=
EH
;
r
->
avl_bf
=
RH
;
break
;
case
EH
:
(
*
root
)
->
avl_bf
=
EH
;
r
->
avl_bf
=
EH
;
break
;
case
RH
:
(
*
root
)
->
avl_bf
=
LH
;
r
->
avl_bf
=
EH
;
break
;
}
l
->
avl_bf
=
EH
;
ROTATERIGHT
(
(
&
r
)
)
(
*
root
)
->
avl_right
=
r
;
ROTATELEFT
(
root
)
shorter
=
1
;
break
;
case
EH
:
/* single rotation left */
(
*
root
)
->
avl_bf
=
RH
;
r
->
avl_bf
=
LH
;
ROTATELEFT
(
root
);
shorter
=
0
;
break
;
case
RH
:
/* single rotation left */
(
*
root
)
->
avl_bf
=
EH
;
r
->
avl_bf
=
EH
;
ROTATELEFT
(
root
)
shorter
=
1
;
break
;
}
break
;
}
return
(
shorter
);
}
/*
* ravl_delete() - called from avl_delete to do recursive deletion of a
* node from an avl tree. It finds the node recursively, deletes it,
* and returns shorter if the tree is shorter after the deletion and
* rebalancing.
*/
static
void
*
ravl_delete
(
Avlnode
**
root
,
void
*
data
,
AVL_CMP
fcmp
,
int
*
shorter
)
{
int
shortersubtree
=
0
;
int
cmp
;
void
*
savedata
;
Avlnode
*
minnode
,
*
savenode
;
if
(
*
root
==
NULLAVL
)
return
(
0
);
cmp
=
(
*
fcmp
)(
data
,
(
*
root
)
->
avl_data
);
/* found it! */
if
(
cmp
==
0
)
{
savenode
=
*
root
;
savedata
=
savenode
->
avl_data
;
/* simple cases: no left child */
if
(
(
*
root
)
->
avl_left
==
0
)
{
*
root
=
(
*
root
)
->
avl_right
;
*
shorter
=
1
;
ber_memfree
(
(
char
*
)
savenode
);
return
(
savedata
);
/* no right child */
}
else
if
(
(
*
root
)
->
avl_right
==
0
)
{
*
root
=
(
*
root
)
->
avl_left
;
*
shorter
=
1
;
ber_memfree
(
(
char
*
)
savenode
);
return
(
savedata
);
}
/*
* avl_getmin will return to us the smallest node greater
* than the one we are trying to delete. deleting this node
* from the right subtree is guaranteed to end in one of the
* simple cases above.
*/
minnode
=
(
*
root
)
->
avl_right
;
while
(
minnode
->
avl_left
!=
NULLAVL
)
minnode
=
minnode
->
avl_left
;
/* swap the data */
(
*
root
)
->
avl_data
=
minnode
->
avl_data
;
minnode
->
avl_data
=
savedata
;
savedata
=
ravl_delete
(
&
(
*
root
)
->
avl_right
,
data
,
fcmp
,
&
shortersubtree
);
if
(
shortersubtree
)
*
shorter
=
right_balance
(
root
);
else
*
shorter
=
0
;
/* go left */
}
else
if
(
cmp
<
0
)
{
if
(
(
savedata
=
ravl_delete
(
&
(
*
root
)
->
avl_left
,
data
,
fcmp
,
&
shortersubtree
))
==
0
)
{
*
shorter
=
0
;
return
(
0
);
}
/* left subtree shorter? */
if
(
shortersubtree
)
*
shorter
=
left_balance
(
root
);
else
*
shorter
=
0
;
/* go right */
}
else
{
if
(
(
savedata
=
ravl_delete
(
&
(
*
root
)
->
avl_right
,
data
,
fcmp
,
&
shortersubtree
))
==
0
)
{
*
shorter
=
0
;
return
(
0
);
}
if
(
shortersubtree
)
*
shorter
=
right_balance
(
root
);
else
*
shorter
=
0
;
}
return
(
savedata
);
}
/*
* avl_delete() - deletes the node containing data (according to fcmp) from
* the avl tree rooted at root.
*/
void
*
avl_delete
(
Avlnode
**
root
,
void
*
data
,
AVL_CMP
fcmp
)
{
int
shorter
;
return
(
ravl_delete
(
root
,
data
,
fcmp
,
&
shorter
)
);
}
static
int
avl_inapply
(
Avlnode
*
root
,
AVL_APPLY
fn
,
void
*
arg
,
int
stopflag
)
{
if
(
root
==
0
)
return
(
AVL_NOMORE
);
if
(
root
->
avl_left
!=
0
)
if
(
avl_inapply
(
root
->
avl_left
,
fn
,
arg
,
stopflag
)
==
stopflag
)
return
(
stopflag
);
if
(
(
*
fn
)(
root
->
avl_data
,
arg
)
==
stopflag
)
return
(
stopflag
);
if
(
root
->
avl_right
==
0
)
return
(
AVL_NOMORE
);
else
return
(
avl_inapply
(
root
->
avl_right
,
fn
,
arg
,
stopflag
)
);
}
static
int
avl_postapply
(
Avlnode
*
root
,
AVL_APPLY
fn
,
void
*
arg
,
int
stopflag
)
{
if
(
root
==
0
)
return
(
AVL_NOMORE
);
if
(
root
->
avl_left
!=
0
)
if
(
avl_postapply
(
root
->
avl_left
,
fn
,
arg
,
stopflag
)
==
stopflag
)
return
(
stopflag
);
if
(
root
->
avl_right
!=
0
)
if
(
avl_postapply
(
root
->
avl_right
,
fn
,
arg
,
stopflag
)
==
stopflag
)
return
(
stopflag
);
return
(
(
*
fn
)(
root
->
avl_data
,
arg
)
);
}
static
int
avl_preapply
(
Avlnode
*
root
,
AVL_APPLY
fn
,
void
*
arg
,
int
stopflag
)
{
if
(
root
==
0
)
return
(
AVL_NOMORE
);
if
(
(
*
fn
)(
root
->
avl_data
,
arg
)
==
stopflag
)
return
(
stopflag
);
if
(
root
->
avl_left
!=
0
)
if
(
avl_preapply
(
root
->
avl_left
,
fn
,
arg
,
stopflag
)
==
stopflag
)
return
(
stopflag
);
if
(
root
->
avl_right
==
0
)
return
(
AVL_NOMORE
);
else
return
(
avl_preapply
(
root
->
avl_right
,
fn
,
arg
,
stopflag
)
);
}
/*
* avl_apply -- avl tree root is traversed, function fn is called with
* arguments arg and the data portion of each node. if fn returns stopflag,
* the traversal is cut short, otherwise it continues. Do not use -6 as
* a stopflag, as this is what is used to indicate the traversal ran out
* of nodes.
*/
int
avl_apply
(
Avlnode
*
root
,
AVL_APPLY
fn
,
void
*
arg
,
int
stopflag
,
int
type
)
{
switch
(
type
)
{
case
AVL_INORDER
:
return
(
avl_inapply
(
root
,
fn
,
arg
,
stopflag
)
);
case
AVL_PREORDER
:
return
(
avl_preapply
(
root
,
fn
,
arg
,
stopflag
)
);
case
AVL_POSTORDER
:
return
(
avl_postapply
(
root
,
fn
,
arg
,
stopflag
)
);
default:
fprintf
(
stderr
,
"Invalid traversal type %d
\n
"
,
type
);
return
(
-
1
);
}
/* NOTREACHED */
}
/*
* avl_prefixapply - traverse avl tree root, applying function fprefix
* to any nodes that match. fcmp is called with data as its first arg
* and the current node's data as its second arg. it should return
* 0 if they match, < 0 if data is less, and > 0 if data is greater.
* the idea is to efficiently find all nodes that are prefixes of
* some key... Like avl_apply, this routine also takes a stopflag
* and will return prematurely if fmatch returns this value. Otherwise,
* AVL_NOMORE is returned.
*/
int
avl_prefixapply
(
Avlnode
*
root
,
void
*
data
,
AVL_CMP
fmatch
,
void
*
marg
,
AVL_CMP
fcmp
,
void
*
carg
,
int
stopflag
)