伸展树定义
伸展树实现
通用头文件 fatal.h
#include <stdio.h>
#include <stdlib.h>
#define Error( Str ) FatalError( Str )
#define FatalError( Str ) fprintf( stderr, "%s\n", Str ), exit( 1 )
声明头文件 splay.h
#include <stdlib.h>
#include "fatal.h"
typedef int ElementType;
#define Infinity 30000
#define NegInfinity (-30000)
#ifndef _Splay_H
#define _Splay_H
struct SplayNode;
typedef struct SplayNode *SplayTree;
SplayTree MakeEmpty( SplayTree T );
SplayTree Find( ElementType X, SplayTree T );
SplayTree FindMin( SplayTree T );
SplayTree FindMax( SplayTree T );
SplayTree Initialize( void );
SplayTree Insert( ElementType X, SplayTree T );
SplayTree Remove( ElementType X, SplayTree T );
ElementType Retrieve( SplayTree T ); /* Gets root item */
#endif /* _Splay_H */
实现文件 splay.c
#include "splay.h"
#include <stdlib.h>
#include "fatal.h"
struct SplayNode
{
ElementType Element;
SplayTree Left;
SplayTree Right;
};
typedef struct SplayNode *Position;
static Position NullNode = NULL; /* Needs initialization */
SplayTree
Initialize( void )
{
if( NullNode == NULL )
{
NullNode = malloc( sizeof( struct SplayNode ) );
if( NullNode == NULL )
FatalError( "Out of space!!!" );
NullNode->Left = NullNode->Right = NullNode;
}
return NullNode;
}
static SplayTree Splay( ElementType Item, Position X );
SplayTree
MakeEmpty( SplayTree T )
{
if( T != NullNode )
{
MakeEmpty( T->Left );
MakeEmpty( T->Right );
free( T );
}
return NullNode;
}
void
PrintTree( SplayTree T )
{
if( T != NullNode )
{
PrintTree( T->Left );
printf( "%d ", T->Element );
PrintTree( T->Right );
}
}
SplayTree
Find( ElementType X, SplayTree T )
{
return Splay( X, T );
}
SplayTree
FindMin( SplayTree T )
{
return Splay( NegInfinity, T );
}
SplayTree
FindMax( SplayTree T )
{
return Splay( Infinity, T );
}
/* This function can be called only if K2 has a left child */
/* Perform a rotate between a node (K2) and its left child */
/* Update heights, then return new root */
// 一字型 从左往右旋转一次
static Position
SingleRotateWithLeft( Position K2 )
{
Position K1;
K1 = K2->Left;
K2->Left = K1->Right;
K1->Right = K2;
return K1; /* New root */
}
/* This function can be called only if K1 has a right child */
/* Perform a rotate between a node (K1) and its right child */
/* Update heights, then return new root */
// 一字型 从右往左旋转
static Position
SingleRotateWithRight( Position K1 )
{
Position K2;
K2 = K1->Right;
K1->Right = K2->Left;
K2->Left = K1;
return K2; /* New root */
}
/* START: fig12_6.txt */
/* Top-down splay procedure, */
/* not requiring Item to be in tree */
// Header用来作为一个 临时根节点 它的右/左子节点只被修改一次 分别指向LeftTreeMax/RightTreeMin最初一次赋值的节点 请注意这里的左右对应关系 理解这个很重要
// LeftTreeMax 左侧子树 通过不断拓展它的右子节点来保证左侧字树的二叉排序性
// RightTreeMin 右侧字数 通过不断拓展它的左子节点来保证右侧子树的二叉排序性
SplayTree
Splay( ElementType Item, Position X )
{
static struct SplayNode Header;
Position LeftTreeMax, RightTreeMin;
Header.Left = Header.Right = NullNode;
LeftTreeMax = RightTreeMin = &Header;
NullNode->Element = Item;
while( Item != X->Element )
{
if( Item < X->Element )
{
if( Item < X->Left->Element )
X = SingleRotateWithLeft( X );
if( X->Left == NullNode )
// 目标item不在tree中 把最后次比较的X当做根节点顶上去
break;
/* Link right */
// 第一个赋值的时候将Header的left指向第一个识别出来的右侧子树的根节点
// 然后接下来不断拓展右子树的左节点 并且移动它
RightTreeMin->Left = X;
RightTreeMin = X;
X = X->Left;
}
else
{
if( Item > X->Right->Element )
X = SingleRotateWithRight( X );
if( X->Right == NullNode )
// 目标item不在tree中 把最后次比较的X当做根节点顶上去
break;
/* Link left */
// 第一个赋值的时候将Header的right指向第一个识别出来的左侧子树的根节点
// 然后接下来不断拓展右子树的右节点 并且移动它
LeftTreeMax->Right = X;
LeftTreeMax = X;
X = X->Right;
}
} /* while Item != X->Element */
/* Reassemble */
// 迭代结束 各个变量值为:
// X:我们的目标item或者最后一次比较的X
// LeftTreeMax 一颗二叉搜索树 所有节点的值都比X的值小
// RightTreeMin 一颗二叉搜索树 所有节点的值都比X的值大
// Header.Right 在第一次被赋值的时候指向了LeftTreeMax的根节点
// Header.Left 在第一次被赋值的时候指向了RightTreeMin的根节点
// 我们把X作为新节点返回即可 以下是交换各个子树的操作
LeftTreeMax->Right = X->Left;
RightTreeMin->Left = X->Right;
X->Left = Header.Right;
X->Right = Header.Left;
return X;
}
/* END */
/* START: fig12_7.txt */
SplayTree
Insert( ElementType Item, SplayTree T )
{
static Position NewNode = NULL;
if( NewNode == NULL )
{
NewNode = malloc( sizeof( struct SplayNode ) );
if( NewNode == NULL )
FatalError( "Out of space!!!" );
}
NewNode->Element = Item;
if( T == NullNode )
{
NewNode->Left = NewNode->Right = NullNode;
T = NewNode;
}
else
{
// 调用一次伸展函数 让根节点距离item很接近 方便进行插入
T = Splay( Item, T );
if( Item < T->Element )
{
NewNode->Left = T->Left;
NewNode->Right = T;
T->Left = NullNode;
T = NewNode;
}
else
if( T->Element < Item )
{
NewNode->Right = T->Right;
NewNode->Left = T;
T->Right = NullNode;
T = NewNode;
}
else
return T; /* Already in the tree */
}
NewNode = NULL; /* So next insert will call malloc */
return T;
}
/* END */
/* START: fig12_8.txt */
SplayTree
Remove( ElementType Item, SplayTree T )
{
Position NewTree;
if( T != NullNode )
{
// 调用一次伸展函数 直接在根节点进行删除
T = Splay( Item, T );
if( Item == T->Element )
{
/* Found it! */
if( T->Left == NullNode )
NewTree = T->Right;
else
{
NewTree = T->Left;
NewTree = Splay( Item, NewTree );
NewTree->Right = T->Right;
}
free( T );
T = NewTree;
}
}
return T;
}
/* END */
ElementType
Retrieve( SplayTree T )
{
return T->Element;
}
参考资料:
《数据结构与算法分析: C语言描述》 www.cnblogs.com/kernel_hcy/…