/* splay.c - code for splay trees Version of August 18, 2001.
* Author : Brendan McKay bdm @ cs . anu . edu . au
This file is not meant to be compiled separately , but to be
# included into other programs . Use it like this :
1 . Define a node type SPLAYNODE . It must be a structure that
contains at least the pointer fields left , right and parent of
type SPLAYNODE * .
Also define a macro SPLAYNODESIZE giving the size of an object
of type SPLAYNODE , unless sizeof ( SPLAYNODE ) is adequate .
2 . Declare a variable of type SPLAYNODE * to point to the root
of the tree , and initialise it to NULL .
3 . Declare SCAN_ARGS to be the additional arguments needed for
splay_scan ( ) , including a leading comma .
4 . Declare ACTION ( p ) for what splay_scan ( ) should do for node p .
5 . Declare INSERT_ARGS to be the additional arguments needed
for splay_insert ( ) , including a leading comma .
6 . Declare COMPARE ( p ) to compare INSERT_ARGS or LOOKUP_ARGS to the
contents of node p . < 0 , 0 , > 0 if INSERT_ARGS is greater , equal ,
less , than p . This has to be an expression with a value , so you will
need to make it a procedure call if the comparison is complicated .
If you are using something like strcmp , the correct order is
strcmp ( INSERT_ARGS , p ) .
7 . Declare PRESENT ( p ) for what to do if INSERT_ARGS is already
present , in node p . There is a spare int variable i available .
Typically , this might update some data in the node p .
8 . Declare NOT_PRESENT ( p ) for what to do if INSERT_ARGS is not
in the tree and p is a fresh node to hold it . No need to set
the left , right , and parent fields . Use i here too if you like .
Typically , this might initialise the data in node p .
PRESENT ( p ) and NOT_PRESENT ( p ) should not manipulate the
tree pointers . However , each of them can include a
return if you don ' t want to change the tree . In the
case of NOT_PRESENT ( p ) , do free ( p ) before returning .
In the case of PRESENT ( p ) , it is also legal to delete the
node from the tree using SCAN_DELETE ( to_root , p ) . In that
case you MUST return immediately afterwards .
9 . Declare LOOKUP_ARGS to be the additional arguments needed
for splay_lookup ( ) , including a leading comma . The default
for LOOKUP_ARGS is to be the same as INSERT_ARGS .
10 . # include " splay . c "
Calls :
Suppose " root " is name of the variable described in step 2 .
There is no need to initialise the tree . Step 2 did that already .
To insert something in the tree :
splay_insert ( & root , . . . stuff . . . )
where " stuff " is the stuff you want to insert , declared as INSERT_ARGS .
If the key ( some part of the stuff decided by you ) is present in an
existing tree node p , PRESENT ( p ) is executed . Otherwise , a new tree
node p is created and NOT_PRESENT ( p ) is executed .
To look up something in the tree :
splay_lookup ( & root , . . . stuff . . . )
where " stuff " is the stuff you want to find , declared as LOOKUP_ARGS .
It will return a pointer to the tree node with the right key , or NULL
if there is no such tree node .
To do something for each node of the tree :
splay_scan ( root , . . . stuff . . . )
where " stuff " is anything you like ( including nothing ) . This will
execute ACTION ( p ) for each node p in inorder .
To delete the node p ( which MUST be in the tree :
splay_delete ( & root , p )
Nothing happens if p is NULL , so you can use
splay_delete ( & root , splay_lookup ( & root , . . . stuff . . . ) )
to delete a node , if any , containing stuff .
It is possible to have splay trees of several types in the same
program . Just include " splay . c " several times , with the procedure
names SPLAY , SPLAY_SCAN , SPLAY_LOOKUP , SPLAY_INSERT , SPLAY_DELETE
defined to distinct names . You have to redefine them all even if
you aren ' t using them all .
*/
#define S_A 0
#define S_L 1
#define S_R 2
#define S_LL 3
#define S_LR 4
#define S_RL 5
#define S_RR 6
#ifndef SPLAYNODESIZE
#define SPLAYNODESIZE sizeof (SPLAYNODE)
#endif
#ifndef LOOKUP_ARGS
#define LOOKUP_ARGS INSERT_ARGS
#endif
#ifndef SPLAY
#define SPLAY splay
#define SPLAY_SCAN splay_scan
#define SPLAY_LOOKUP splay_lookup
#define SPLAY_INSERT splay_insert
#define SPLAY_DELETE splay_delete
#endif
/*********************************************************************/
void
SPLAY_SCAN(SPLAYNODE *root SCAN_ARGS)
/* Do ACTION(p) for each node of the tree, in inorder. Nonrecursive! */
{
int code;
SPLAYNODE *p;
p = root;
code = S_A;
while (p)
{
switch (code) /* deliberate flow-ons */
{
case S_A:
if (p->left)
{
p = p->left;
break ;
}
case S_L:
ACTION(p);
if (p->right)
{
p = p->right;
code = S_A;
break ;
}
case S_R:
if (p->parent && p->parent->left == p) code = S_L;
else code = S_R;
p = p->parent;
break ;
}
}
}
/*********************************************************************/
static void
SPLAY(SPLAYNODE *p)
/* Splay the node p. It becomes the new root. */
{
SPLAYNODE *q,*r,*s;
SPLAYNODE *a,*b,*c;
int code;
#define LCHILD(x,y) {(x)->left = y; if (y) (y)->parent = x;}
#define RCHILD(x,y) {(x)->right = y; if (y) (y)->parent = x;}
while (p->parent)
{
a = p->left;
b = p->right;
q = p->parent;
if (q->left == p)
{
code = S_L;
c = q->right;
}
else
{
code = S_R;
c = q->left;
}
r = q->parent;
if (r)
{
if (r->left == q) code = (code == S_L ? S_LL : S_LR);
else code = (code == S_L ? S_RL : S_RR);
s = r->parent;
p->parent = s;
if (s)
{
if (s->left == r) s->left = p;
else s->right = p;
}
}
else
{
p->parent = NULL;
}
switch (code)
{
case S_L:
RCHILD(p,q);
LCHILD(q,b);
break ;
case S_R:
LCHILD(p,q);
RCHILD(q,a);
break ;
case S_LL:
RCHILD(p,q);
RCHILD(q,r);
LCHILD(q,b);
LCHILD(r,c);
break ;
case S_RR:
LCHILD(p,q);
LCHILD(q,r);
RCHILD(r,c);
RCHILD(q,a);
break ;
case S_LR:
LCHILD(p,q);
RCHILD(p,r);
RCHILD(q,a);
LCHILD(r,b);
break ;
case S_RL:
LCHILD(p,r);
RCHILD(p,q);
RCHILD(r,a);
LCHILD(q,b);
break ;
}
}
}
/*********************************************************************/
void
SPLAY_INSERT(SPLAYNODE **to_root INSERT_ARGS)
/* Do insertion operation. On return, the object being inserted
is at the root of the tree regardless of whether a new node
needed to be created for it. */
{
int i,cmp;
SPLAYNODE *p,*ppar,*new_node;
p = *to_root;
cmp = 0 ;
while (p != NULL)
{
cmp = COMPARE(p);
if (cmp == 0 )
{
PRESENT(p);
SPLAY(p);
*to_root = p;
return ;
}
else if (cmp < 0 )
{
ppar = p;
p = p->left;
}
else
{
ppar = p;
p = p->right;
}
}
if ((new_node = (SPLAYNODE*)malloc(SPLAYNODESIZE)) == NULL)
{
fprintf(stderr,">E malloc failed in splay_insert()\n" );
exit (1 );
}
NOT_PRESENT(new_node);
new_node->left = new_node->right = NULL;
if (cmp == 0 )
{
*to_root = new_node;
new_node->parent = NULL;
}
else if (cmp < 0 )
{
ppar->left = new_node;
new_node->parent = ppar;
}
else
{
ppar->right = new_node;
new_node->parent = ppar;
}
SPLAY(new_node);
*to_root = new_node;
}
/*********************************************************************/
SPLAYNODE*
SPLAY_LOOKUP(SPLAYNODE **to_root LOOKUP_ARGS)
/* Do a look-up operation. If found, return a pointer to the
node containing it. If not, return NULL. */
{
int i,cmp; /* i is available for COMPARE */
SPLAYNODE *p;
p = *to_root;
cmp = 0 ;
while (p != NULL)
{
cmp = COMPARE(p);
if (cmp == 0 )
{
SPLAY(p);
*to_root = p;
return p;
}
else if (cmp < 0 )
p = p->left;
else
p = p->right;
}
return NULL;
}
/*********************************************************************/
void
SPLAY_DELETE(SPLAYNODE **to_root, SPLAYNODE *p)
/* Remove node p from the tree and free it. */
{
SPLAYNODE *q;
if (p == NULL) return ;
SPLAY(p);
*to_root = p;
/* Now we have to delete the root. */
/* No right child (includes no children). */
if (!p->right)
{
*to_root = p->left;
if (p->left) p->left->parent = NULL;
free(p);
return ;
}
/* right child but no left child */
if (!p->left)
{
*to_root = p->right;
p->right->parent = NULL;
free(p);
return ;
}
/* both children exist */
for (q = p->left; q->right; q = q->right) {}
if (q->left) q->left->parent = q->parent;
if (q->parent == p) q->parent->left = q->left;
else q->parent->right = q->left;
q->left = p->left;
q->right = p->right;
q->parent = NULL;
if (p->left) p->left->parent = q;
if (p->right) p->right->parent = q;
*to_root = q;
free(p);
}
/*********************************************************************/
/* The following shows the tree structure for debugging purposes.
If you define SPLAY_DUMP you must also define DUMP_ARGS ,
DUMP_LEFT, DUMP_RIGHT and DUMP_ACTION(p). */
#ifdef SPLAY_DUMP
void
SPLAY_DUMP(SPLAYNODE *p DUMP_ARGS)
{
int i;
if (p == NULL) return ;
if (p->right && p->right->parent != p)
fprintf(stderr,"parent misaligned at %p-%p ************\n" ,p,p->right);
if (p->left && p->left->parent != p)
fprintf(stderr,"parent misaligned at %p-%p ************\n" ,p,p->left);
SPLAY_DUMP(p->right DUMP_RIGHT);
DUMP_ACTION(p);
SPLAY_DUMP(p->left DUMP_LEFT);
}
#endif
Messung V0.5 in Prozent C=96 H=89 G=92
¤ Dauer der Verarbeitung: 0.23 Sekunden
(vorverarbeitet am 2026-06-15)
¤
*© Formatika GbR, Deutschland