伸展树 - 二叉搜索树的扩展2
目录
1. 舒展树的介绍舒展树(splay tree)是1种搜索2叉树,它能在 舒展树的动身点是这样的:斟酌到局部性原理(刚被访问的内容下次更大的可能仍会被访问)和28原则(80%的时间只会访问20%的节点),为了使全部查找时间更小,被查找频率高的节点应当常常处于靠近根的位置。 2. 舒展树的C实现以下舒展树的实现思想来源于2叉搜索树的根插法(先插入节点到叶子,然后递归旋转到根),我们将查找到的节点旋转到根,等价于将被查找节点插入到根部: 2.1 节点定义typedef SplayTreeNode* SplayTree;
struct SplayTreeNode {
Item key;
SplayTree left;
SplayTree right;
}; 舒展树不需要记录额外甚么值(如AVL的高度)来保护树的信息,节省了内存。 2.2 旋转引入两种基本的旋转:左旋和右旋 //右旋--k2是根,k1是k2的左子树,将k1旋转成根 -- 以k2为原点向右旋
SplayTree rotR(SplayTree k2)
{
SplayTree k1 = k2->left;
k2->left = k1->right;
k1->right = k2;
return k1;
}
//左旋---k2是根,k1是k2的右子树,(k1的右子树非空)将k1旋转成根 -- 以k2为原点向左旋
SplayTree rotL(SplayTree k2)
{
SplayTree k1 = k2->right;
k2->right = k1->left;
k1->left = k2;
return k1;
} 2.3 舒展树的舒展 递归实现进程是自底向上的,当查找节点命中后,以它的父节点为轴旋转,提升查找节点为根;向上递归,在根与查找节点的路径上每步都旋转1次,直至原树根。 //舒展进程:将key对应的节点舒展到根上,并返回根节点
SplayTree Splay(SplayTree tree,Item key)
{
if (tree == NULL)
return tree;
if (key == tree->key) //命中
return tree;
if (key < tree->key) { //左边
if (tree->left == NULL)
return tree;
tree->left = Splay(tree->left,key);
tree = rotR(tree);
} else { //右边
if (tree->right == NULL)
return tree;
tree->right = Splay(tree->right,key);
tree = rotL(tree);
}
return tree;
} 2.4 搜索SplayTree SplayTreeSearch(SplayTree tree,Item key)
{
if (tree == NULL || tree->key == key)
return tree;
if (key < tree->key)
return SplayTreeSearch(tree->left,key);
else
return SplayTreeSearch(tree->right,key);
} 2.4 舒展树的插入和删除(1)插入:和搜索2叉树的插入相同,省略 (2)删除: 删除舒展树中键值为key的节点。 /*
*删除舒展树中键值为key的节点
*参数说明:
* tree: 根节点
* key: 待删除节点的键值
*返回:
* 根节点
*/
SplayTree SplayTreeDelete(SplayTree tree,Item key)
{
SplayTree x = NULL;
if (tree == NULL)
return tree;
tree = Splay(tree,key);
if (tree == NULL)
return tree;
if (tree->left != NULL) {
//将根的左边,邻近key的节点旋转成根
x = Splay(tree->left,key);
x->right = tree->right;
} else {
//tree->left == NULL
x = tree->right;
}
delete tree;
return x;
} 3. 全部代码和参考资料#include <stdio.h>
#include <stdlib.h>
#define MAX(A,B) ((A > B) ? A : B)
typedef int Item;
typedef struct SplayTreeNode SplayTreeNode;
typedef SplayTreeNode* SplayTree;
struct SplayTreeNode {
Item key;
SplayTree left;
SplayTree right;
};
static int g_error = 0; //毛病代码
SplayTree NewNode(Item key,SplayTree left,SplayTree right)
{
SplayTree x = (SplayTree)malloc(sizeof(*x));
if (x == NULL) {
g_error = 1;
exit(-1);
}
x->key = key;
x->left = left;
x->right = right;
return x;
}
SplayTree SplayTreeInit()
{
return NewNode(10,NULL,NULL);
}
//左旋---k2是根,k1是k2的右子树,(k1的右子树非空)将k1旋转成根 -- 以k2为原点向左旋
SplayTree rotL(SplayTree k2)
{
SplayTree k1 = k2->right;
k2->right = k1->left;
k1->left = k2;
return k1;
}
//右旋--k2是根,k1是k2的左子树,将k1旋转成根 -- 以k2为原点向右旋
SplayTree rotR(SplayTree k2)
{
SplayTree k1 = k2->left;
k2->left = k1->right;
k1->right = k2;
return k1;
}
SplayTree Splay(SplayTree tree,Item key)
{
if (tree == NULL)
return tree;
if (key == tree->key)
return tree;
if (key < tree->key) { //左边
if (tree->left == NULL)
return tree;
tree->left = Splay(tree->left,key);
tree = rotL(tree);
}
return tree;
}
SplayTree SplayTreeSearch(SplayTree tree,key);
}
SplayTree SplayTreeInsert(SplayTree tree,Item key)
{
if (tree == NULL)
return NewNode(key,NULL);
if(key < tree->key)
tree->left = SplayTreeInsert(tree->left,key);
else
tree->right = SplayTreeInsert(tree->right,key);
return tree;
}
void traversal(SplayTree tree)
{
if (tree == NULL) {
printf("NIL ");
return;
}
printf("%d ",tree->key);
traversal(tree->left);
traversal(tree->right);
return;
}
SplayTree SplayTreeDelete(SplayTree tree,key);
if (tree == NULL)
return tree;
if (tree->left != NULL) {
x = Splay(tree->left,key);
x->right = tree->right;
} else {
//tree->left == NULL
x = tree->right;
}
delete tree;
return x;
}
int main()
{
SplayTree splay_tree = NULL;
//for (int i = 0; i < 10; i++) {
// int key = rand()%100;
// splay_tree = SplayTreeInsert(splay_tree,key);
// printf("%d ",key);
//}
splay_tree = SplayTreeInsert(splay_tree,1);
splay_tree = SplayTreeInsert(splay_tree,5);
splay_tree = SplayTreeInsert(splay_tree,4);
splay_tree = SplayTreeInsert(splay_tree,2);
splay_tree = SplayTreeInsert(splay_tree,6);
printf("
Traversal
");
traversal(splay_tree);
splay_tree = Splay(splay_tree,6);
splay_tree = SplayTreeDelete(splay_tree,4);
printf("
Deleted Traversal
");
traversal(splay_tree);
getchar();
} 参考资料: (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |