您的位置:首页 > 理论基础 > 数据结构算法

高级数据结构实现——自顶向下伸展树

2016-01-29 22:34 549 查看

【0】README

1) 本文部分内容转自 数据结构与算法分析,旨在理解 高级数据结构实现——自顶向下伸展树 的基础知识;
2) 源代码部分思想借鉴了数据结构与算法分析,有一点干货原创代码,for original source code, please visithttps://github.com/pacosonTang/dataStructure-algorithmAnalysis/tree/master/chapter12/p345_topdown_splay_tree
3) you can also refer to the link /article/4582418.html

4) for basic splay tree , please visit http://blog.csdn.net/PacosonSWJTU/article/details/50525435

【1】自顶向下伸展树相关

1)problem+solution

1.1)problem: 普通伸展树的展开操作需要从根沿树往下的一次遍历, 以及而后的从底向上的一次遍历。(详情,参见:http://blog.csdn.net/pacosonswjtu/article/details/50525435) 这可以通过保存一些父指针来完成, 或者通过将访问路径存储到一个栈中来完成。 但遗憾的 是, 这两种方法均需要大量的开销 ;

1.2)solution: 本节中, 我们指出如何在初始访问路径上施行一些旋转。结果得到在时间中更快的过程,只用到 O(1)的额外空间, 但却保持了 O(logN) 的摊还时间界;(干货——伸展树是基于AVL树的, 在AVL的基础上引入伸展树的目的是保持他的摊还时间界为 O(logN))

2)对伸展树的自顶向下的旋转操作:(单旋转+一字型旋转+之字型旋转)

2.1)这种伸展方式会把树切成三份,L树,M树,R树,考虑的情况有:单旋转,“一字型”旋转,“之字形”旋转。起初左树(L) 和 右树(R)均为空(NULL);







3)看个荔枝:

3.1)splay + deleting opeartions:





3.2)inserting opeartions:





4)source code at a glance

#include "topdown_splay_tree.h"

// allocate memory for new node.
Node makeNode(int value)
{
Node node;

node = (Node)malloc(sizeof(struct Node));
if(!node)
{
Error("failed makeNode, for out of space !");
return NULL;
}
node->left = NULL;
node->right = NULL;
node->value = value;

return node;
}

// left left single rotate
TopDownSplayTree left_left_single_rotate(TopDownSplayTree root)
{
TopDownSplayTree temp;

temp = root; // 1st step
root = root->left; // 2nd step
temp->left = root->right; // 3rd step
root->right = temp; // 4th step

return root;
}

// right_right_single_rotate
TopDownSplayTree right_right_single_rotate(TopDownSplayTree root)
{
TopDownSplayTree temp;

temp = root; // 1st step
root = root->right; // 2nd step
temp->right = root->left; // 3rd step
root->left = temp; // 4th step

return root;
}

// performing splay operations
TopDownSplayTree topdown_splay(int value, TopDownSplayTree middle)
{
struct Node plusTree;
Node leftTreeMax;
Node rightTreeMin;

leftTreeMax = &plusTree;
rightTreeMin = &plusTree;

while(value != middle->value)
{
if(middle->value < value)  // the new node is greater.
{
if(middle->right == NULL)
{
break;
}
else if(middle->right->value < value && middle->right->right)
{
middle = right_right_single_rotate(middle);
}
leftTreeMax->right = middle;
leftTreeMax = middle;
middle = middle->right;
leftTreeMax->right = NULL;
}

if(middle->value > value) // the new node is less.
{
if(middle->left == NULL)
{
break;
}
else if(middle->left->value > value && middle->left->left)
{
middle = left_left_single_rotate(middle);
}
rightTreeMin->left = middle;
rightTreeMin = middle;
middle = middle->left;
rightTreeMin->left = NULL;
}
}

leftTreeMax->right = middle->left;
rightTreeMin->left = middle->right;
middle->left = plusTree.right;
middle->right = plusTree.left;

return middle;
}

// delete the root of the  TopDownSplayTree
TopDownSplayTree deleteNode(int value, TopDownSplayTree root)
{
TopDownSplayTree newroot;

if(root == NULL)
{
return root;
}
else // the splay tree is not null
{
root = topdown_splay(value, root);
if(root->value == value)  // find the node with given value.
{
if(root->left == NULL)
{
newroot = root->right;
}
else
{
newroot = root->left;
// perform splay again with value towards the left subtree which is not null.
newroot = topdown_splay(value, newroot);
newroot->right = root->right;
}
free(root);
root = newroot;
}
}

return root;
}

// insert the node with value into the TopDownSplayTree
TopDownSplayTree insert(int value, TopDownSplayTree root)
{
TopDownSplayTree node;

node = makeNode(value);

if(root == NULL) // the splay tree is null
{
return node;
}
else // the splay tree is not null
{
root = topdown_splay(value, root);

if(root->value > value)
{
node->left = root->left;
node->right = root;
root->left = NULL;
root = node;
}
else if(root->value < value)
{
node->right = root->right;
root->right = NULL;
node->left = root;
root = node;
}
else
{
return root;
}
}

return root;
}

// test for insert operation.
int main1()
{
TopDownSplayTree root;
int data[] = {5, 11, 23, 10, 17};
int size = 5;
int i;

printf("\n === executing insert with {5, 11, 23, 10, 17} in turn.=== \n");
root = NULL;
for(i=0; i<size; i++)
{
root = insert(data[i], root);
printPreorder(1, root);
}

printf("\n === executing insert with 8 in turn.=== \n");
root = insert(8, root);
printPreorder(1, root);

printf("\n === executing insert with 18 in turn.=== \n");
root = insert(18, root);
printPreorder(1, root);

return 0;
}

// test for splay operation and deleting operation.
int main()
{
TopDownSplayTree root;
TopDownSplayTree temp;

printf("\n ====== test for splaying operation====== \n");
printf("\n === original tree is as follows.=== \n");
root = makeNode(12); // root = 12
temp = root;
temp->left = makeNode(5);
temp->right = makeNode(25);

temp = temp->right;  // root = 25
temp->left = makeNode(20);
temp->right = makeNode(30);

temp = temp->left;  // root = 20
temp->left = makeNode(15);
temp->right = makeNode(24);

temp = temp->left;  // root = 15
temp->left = makeNode(13);
temp->right = makeNode(18);

temp = temp->right;  // root = 18
temp->left = makeNode(16);

printPreorder(1, root);

printf("\n === executing splay operation with finding value=19.=== \n");
root = topdown_splay(19, root);
printPreorder(1, root);

printf("\n === executing deleting operation with value=15.=== \n");
root = deleteNode(15, root);
printPreorder(1, root);

return 0;
}

// analog print node values in the binominal tree, which involves preorder traversal.
void printPreorder(int depth, TopDownSplayTree root)
{
int i;

if(root)
{
for(i = 0; i < depth; i++)
printf("    ");
printf("%d\n", root->value);
printPreorder(depth + 1, root->left);
printPreorder(depth + 1, root->right);
}
else
{
for(i = 0; i < depth; i++)
printf("    ");
printf("NULL\n");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: