typedef struct Node
{
int key;
struct Node *lch,*rch,*parent;
}* Node ,* Tree;
下面几个函数中,设x 的父节点为 p, p的父节点为g 。
//单次右旋以 root 节点 为根节点的树
Node zig( Tree tree , Node root)
{
Node lc = root->lch;
Node parent = root->parent;
//处理父节点关系
if( parent )
{
if( root == parent->lch )
{
parent->lch = lc;
}else{
parent->rch = lc;
}
lc->parent = parent;
}else{
lc->parent = NULL;
}
//翻转
if( lc != NULL )
{
root->lch = lc->rch;
if( lc->rch )
{
lc->rch->parent = root;
}
lc->rch = root;
root->parent = lc;
if( parent )
{
return tree;
}else{
return lc;
}
}
return tree;
}
//单次左旋以 root 节点 为根节点的树
Node zag( Tree tree , Node root)
{
Node rc = root->rch;
Node parent = root->parent;
//处理父节点关系
if( parent )
{
if( root == parent->lch )
{
parent->lch = rc;
}else{
parent->rch = rc;
}
rc->parent = parent;
}else{
rc->parent = NULL;
}
//翻转
if( rc != NULL )
{
root->rch = rc->lch;
if( rc->lch )
{
rc->lch->parent = root;
}
rc->lch = root;
root->parent = rc;
if( parent )
{
return tree;
}else{
return rc;
}
}
return tree;
}
//右双旋以 root 节点 为根节点的树
Node zig_zig( Tree tree , Node root)
{
Node lc = root->lch;
Node node=zig( tree , root );
return zig( node , lc );
}
//左双旋以 root 节点 为根节点的树
Node zag_zag( Tree tree , Node root)
{
Node rc = root->rch;
Node node=zag( tree , root );
return zag( node , rc );
}
Node zig_zag( Tree tree , Node root)
{
Node node=zig( tree , root->rch );
return zag( node , root );
}
Node zag_zig( Tree tree , Node root)
{
Node node=zag( tree , root->lch );
return zig( node , root );
}
//根据目标节点的结构选择相应的算法,策略模式
Node zig_zag_manager( Tree tree , Node node )
{
Node parent = node->parent;
if( parent == tree ) //1
{
if( parent->lch == node )
{
return zig( tree , parent );
}else{
return zag( tree , parent );
}
}else if( parent->lch == node ){ //2
Node grand = parent->parent;
if( grand->lch == parent ){ /*左左*/
return zig_zig( tree , grand );
}else{ /*右左*/
return zig_zag( tree , grand );
}
}else if( parent->rch == node ){ //3
Node grand = parent->parent;
if( grand->lch == parent ){ /*左右*/
return zag_zig( tree , grand );
}else{ /*右右*/
return zag_zag( tree , grand );
}
}
return tree;
}
//将目标节点调整到树的根部,并返回树根
Node splay(Tree tree , Node node)
{
while( node->parent!=NULL )
{
zig_zag_manager( tree , node );
}
return node;
}
//寻找key节点
Node find( Tree tree , int key )
{
Node curr = tree;
while( curr != NULL )
{
if( curr->key == key ){
splay( tree , curr );
return curr;
} else if( curr->key > key ){
curr = curr->lch;
}else{
curr = curr->rch;
}
}
return NULL;
}
//以 node 为届,分离 tree 的左子树 ,返回剩余部分
Node spilt( Tree tree , Node node )
{
tree = splay( tree , node ); //将 node 调至根部
Node lc = tree->lch;
tree->lch = NULL;
if( lc )
{
lc->parent = NULL;
}
return tree;
}
注意这里,要获得左子树可以在分离之前获得。
//合并tree1 和 tree2 ,要求 tree1 所有元素小于 tree2 任一元素
Node join( Tree tree1, Tree tree2)
{
//找打 tree1 中最大的元素
Node temp = tree1;
while( temp->rch != NULL )
{
temp = temp->rch;
}
//将 temp调至 tree1的根部
splay( tree1 ,temp );
//将 tree2 作为 temp的右子树
temp->rch = tree2;
tree2->parent = temp;
return temp;
}
附件:
1. C-free工程,也可直接打开文件.zip
2. 广东工业大学-计算机学院-伸展树.pdf