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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高级数据结构实现——自顶向下伸展树相关的知识,希望对你有一定的参考价值。

【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 http://www.cnblogs.com/huangxincheng/archive/2012/08/04/2623455.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");
    }
} 

 

 

 

以上是关于高级数据结构实现——自顶向下伸展树的主要内容,如果未能解决你的问题,请参考以下文章

邓俊辉数据结构学习-8-1-伸展树

UVA 11922 Permutation Transformer —— splay伸展树

Splay(伸展树分裂树):平衡二叉搜索树中功能最丰富的树

高级搜索树

Splay伸展树

Splay Tree(伸展树)