《树》之伸展树
2016-01-30 19:34
316 查看
本文介绍什么?
使用伸展树有什么样的效果;
伸展树的定义;
伸展树ADT具体实现过程的描述;
代码实现。
一、使用伸展树(splay tree)的效果:
使用伸展树时,对伸展树上任意一次操作的最坏运行时间为 O( N );但是,它保证了连续M次操作花费的最多时间为O(M ㏒N),从而可以推算出对伸展树的每一次操作的摊还时间为O( ㏒N)。
二、伸展树的定义:
对于一颗二查查找树进行操作时,每访问一个节点,该节点都通过旋转操作被放到根上。这样的一颗二查查找树称为伸展树。
三、伸展树ADT的描述:
1.伸展树的节点定义与二查查找树节点定义的方法一致,此处不再赘述;
2.比起二查查找树,伸展树ADT只是对了一个旋转操作。在这里的旋转,我们称之为展开(Splaying)。设节点X为访问的节点,我们通过对节点X进行一系列操作,将节点X移动到根节点。
3.节点X旋转的情况:
⑴节点X为根节点:什么都不做;
⑵节点X的父节点为根节点:
根节点的左子树=X的右子树;
X的右子树=根节点;
⑶节点X具有父节点(P)、祖父节点(G),此时有(两类)四种情况需要考虑:
ⅰ、( "一" 字形) P是G的左儿子,X是P的左儿子;
ⅱ、( "一" 字形)P是G的右儿子,X是P的右儿子;
ⅲ、( "之" 字形)P是G的左儿子,X是P的右儿子;
ⅳ、( "之" 字形)P是G的右儿子,X是P的左儿子;
4.节点的删除:
由于对节点X的每一次访问都需要将X移向根节点,所以懒惰删除在这里显得不太合适,在这里需要进行的直接删除。当进行删除操作时,首先需要访问节点X,节点X被移动到根节点,此时删除X花费的代价是比较小的。在删除节点X的时候,①访问X导致节点X被移向根节点,删除节点X并得到左、右两棵子树(TL、TR);②在右子树TR上访问最小节点Y(该节点一定没有左儿子),将Y移动到右子树的根节点;③令Y的左儿子为左子树TL。
四、核心代码实现:
1.伸展树的伸展实现
ⅰ、( "一" 字形) P是G的左儿子,X是P的左儿子;
操作:
G的左儿子=P的右儿子;
P的右儿子=G;
P的左儿子=X的右儿子;
X的右儿子=P;
ⅱ、( "一" 字形)P是G的右儿子,X是P的右儿子;
操作:
G的右儿子=P的左儿子;
P的左儿子=G;
P的右儿子=X的左儿子;
X的左儿子=P;
ⅲ、( "之" 字形)P是G的左儿子,X是P的右儿子;
操作:
G的左儿子=X的右儿子;
X的右儿子=G;
P的右儿子=X的左儿子;
X的左儿子=P;
ⅳ、( "之" 字形)P是G的右儿子,X是P的左儿子;
操作:
G的右儿子=X的左儿子;
X的左儿子=G;
P的左儿子=X的右儿子;
X的右儿子=P;
3.伸展树的删除操作实现
使用伸展树有什么样的效果;
伸展树的定义;
伸展树ADT具体实现过程的描述;
代码实现。
一、使用伸展树(splay tree)的效果:
使用伸展树时,对伸展树上任意一次操作的最坏运行时间为 O( N );但是,它保证了连续M次操作花费的最多时间为O(M ㏒N),从而可以推算出对伸展树的每一次操作的摊还时间为O( ㏒N)。
二、伸展树的定义:
对于一颗二查查找树进行操作时,每访问一个节点,该节点都通过旋转操作被放到根上。这样的一颗二查查找树称为伸展树。
三、伸展树ADT的描述:
1.伸展树的节点定义与二查查找树节点定义的方法一致,此处不再赘述;
2.比起二查查找树,伸展树ADT只是对了一个旋转操作。在这里的旋转,我们称之为展开(Splaying)。设节点X为访问的节点,我们通过对节点X进行一系列操作,将节点X移动到根节点。
3.节点X旋转的情况:
⑴节点X为根节点:什么都不做;
⑵节点X的父节点为根节点:
根节点的左子树=X的右子树;
X的右子树=根节点;
⑶节点X具有父节点(P)、祖父节点(G),此时有(两类)四种情况需要考虑:
ⅰ、( "一" 字形) P是G的左儿子,X是P的左儿子;
ⅱ、( "一" 字形)P是G的右儿子,X是P的右儿子;
ⅲ、( "之" 字形)P是G的左儿子,X是P的右儿子;
ⅳ、( "之" 字形)P是G的右儿子,X是P的左儿子;
4.节点的删除:
由于对节点X的每一次访问都需要将X移向根节点,所以懒惰删除在这里显得不太合适,在这里需要进行的直接删除。当进行删除操作时,首先需要访问节点X,节点X被移动到根节点,此时删除X花费的代价是比较小的。在删除节点X的时候,①访问X导致节点X被移向根节点,删除节点X并得到左、右两棵子树(TL、TR);②在右子树TR上访问最小节点Y(该节点一定没有左儿子),将Y移动到右子树的根节点;③令Y的左儿子为左子树TL。
四、核心代码实现:
1.伸展树的伸展实现
ⅰ、( "一" 字形) P是G的左儿子,X是P的左儿子;
操作:
G的左儿子=P的右儿子;
P的右儿子=G;
P的左儿子=X的右儿子;
X的右儿子=P;
//一字形(左左) static Position ZigzigLL(Position g) { Position p,x; p=g->left;x=p->left; g->left=p->right; p->right=g; p->left=x->right; x->right=p; return x; }
ⅱ、( "一" 字形)P是G的右儿子,X是P的右儿子;
操作:
G的右儿子=P的左儿子;
P的左儿子=G;
P的右儿子=X的左儿子;
X的左儿子=P;
//一字形(右右) static Position ZigzigRR(Position g) { Position p,x; p=g->right;x=p->right; g->right=p->left; p->left=g; p->right=x->left; x->left=p; return x; }
ⅲ、( "之" 字形)P是G的左儿子,X是P的右儿子;
操作:
G的左儿子=X的右儿子;
X的右儿子=G;
P的右儿子=X的左儿子;
X的左儿子=P;
//一字形(左右) static Position ZigzigLR(Position g) { Position p,x; p=g->left;x=p->right; g->left=x->right; x->right=g; p->right=x->left; x->left=p; return x; }
ⅳ、( "之" 字形)P是G的右儿子,X是P的左儿子;
操作:
G的右儿子=X的左儿子;
X的左儿子=G;
P的左儿子=X的右儿子;
X的右儿子=P;
//一字形(右左) static Position ZigzigRL(Position g) { Position p,x; p=g->right;x=p->left; g->right=x->left; x->left=g; p->left=x->right; x->right=p; return x; }
3.伸展树的删除操作实现
//删除节点 void Delete(const ElementType x,const sTree st) { if(NULL==st) printf("该树为空树\n"); else{ position temp=Find(x,st); Position root=FindMin(temp->right); root->left=temp->left; free(temp); temp=NULL; return ; } }
相关文章推荐
- C#数据结构之顺序表(SeqList)实例详解
- Lua教程(七):数据结构详解
- 解析从源码分析常见的基于Array的数据结构动态扩容机制的详解
- C#数据结构之队列(Quene)实例详解
- C#数据结构揭秘一
- C#数据结构之单链表(LinkList)实例详解
- 数据结构之Treap详解
- C#数据结构之堆栈(Stack)实例详解
- C#数据结构之双向链表(DbLinkList)实例详解
- JavaScript数据结构和算法之图和图算法
- Java数据结构及算法实例:冒泡排序 Bubble Sort
- Java数据结构及算法实例:插入排序 Insertion Sort
- Java数据结构及算法实例:考拉兹猜想 Collatz Conjecture
- java数据结构之java实现栈
- java数据结构之实现双向链表的示例
- Java数据结构及算法实例:选择排序 Selection Sort
- Java数据结构及算法实例:朴素字符匹配 Brute Force
- Java数据结构及算法实例:汉诺塔问题 Hanoi
- Java数据结构及算法实例:快速计算二进制数中1的个数(Fast Bit Counting)
- java数据结构和算法学习之汉诺塔示例