这本书在第四章给出了(自底向上)伸展树的描述,但没有给出对应的代码。
其第十二章描述了自顶向下伸展树,且给出了代码。作为附带,描述了一些与第四章实现相关的细节,但由于其情况多样,实现起来仍旧相当困难。
这里给出其第四章伸展树的伸展和插入的实现,没有使用第十二章所描述的父链与栈。(不保证无错,希望读者能给出建议)
Splay.h
#ifndef _Splay_H
struct SplayNode;
typedef struct SplayNode *SplayTree;
typedef int ElementType;
SplayTree MakeEmpty( SplayTree T );
SplayTree Find( ElementType X, SplayTree T );
SplayTree FindMin( SplayTree T );
SplayTree FindMax( SplayTree T );
SplayTree Insert( ElementType X, SplayTree T );
SplayTree Remove( ElementType X, SplayTree T );
ElementType Retrieve( SplayTree T );
void PrintTree( SplayTree T );
#endif
Splay.c
#include "Splay.h"
#include "Error.h"
#include <stdlib.h>
#include <stdio.h>
struct SplayNode
{
ElementType Element;
SplayTree Left;
SplayTree Right;
};
typedef struct SplayNode *Position;
static Position Root = NULL;
static Position
SingleRotateWithLeft( Position K2 )
{
Position K1;
K1 = K2->Left;
K2->Left = K1->Right;
K1->Right = K2;
return K1;
}
static Position
SingleRotateWithRight( Position K1 )
{
Position K2;
K2 = K1->Right;
K1->Right = K2->Left;
K2->Left = K1;
return K2;
}
static Position
DoubleRotateWithLeft( Position K3 )
{
K3->Left = SingleRotateWithRight( K3->Left );
return SingleRotateWithLeft( K3 );
}
static Position
DoubleRotateWithRight( Position K3 )
{
K3->Right = SingleRotateWithLeft( K3->Right );
return SingleRotateWithRight( K3 );
}
static SplayTree
SplayWithRoot( ElementType Item, Position T )
{
if ( T != NULL && T->Element != Item )
{
if ( T->Left != NULL &&
T->Left->Element == Item )
//zig
T = SingleRotateWithLeft( T );
else
if ( T->Right != NULL &&
T->Right->Element == Item )
//zag
T = SingleRotateWithRight( T );
}
return T;
}
static SplayTree
SplayWithLeft( ElementType Item, Position T )
{
if ( T != NULL && T->Left != NULL )
{
if ( T->Left->Right != NULL &&
T->Left->Right->Element == Item )
//zig-zag
T = DoubleRotateWithLeft( T );
else
if ( T->Left->Left != NULL &&
T->Left->Left->Element == Item )
{
//zig-zig
T = SingleRotateWithLeft( T );
T = SingleRotateWithLeft( T );
}
}
return T;
}
static SplayTree
SplayWithRight( ElementType Item, Position T )
{
if ( T != NULL && T->Right != NULL )
{
if ( T->Right->Left != NULL &&
T->Right->Left->Element == Item )
//zag-zig
T = DoubleRotateWithRight( T );
else
if ( T->Right->Right != NULL &&
T->Right->Right->Element == Item )
{
//zag-zag
T = SingleRotateWithRight( T );
T = SingleRotateWithRight( T );
}
}
return T;
}
static SplayTree
insert( ElementType X, SplayTree T )
{
if ( T == NULL )
{
T = malloc( sizeof( struct SplayNode ) );
if ( T == NULL )
FatalError( "Out of space!!!" );
T->Element = X;
T->Left = NULL;
T->Right = NULL;
}
else
if ( X < T->Element )
{
T->Left = insert( X, T->Left );
T = SplayWithLeft( X, T );
}
else
if ( X > T->Element )
{
T->Right = insert( X, T->Right );
T = SplayWithRight( X, T );
}
if ( T == Root )
return SplayWithRoot( X, T );
return T;
}
SplayTree
Insert( ElementType X, SplayTree T )
{
Root = T;
return insert( X, T );
}