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

【0】README

1) 本文部分内容转自 数据结构与算法分析,旨在理解 高级数据结构实现——自顶向下伸展树 的基础知识;
2) 源代码部分思想借鉴了数据结构与算法分析,有一点干货原创代码,for original source code, please visit https://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);

    高级数据结构实现——自顶向下伸展树_第1张图片

3)看个荔枝:

  • 3.1)splay + deleting opeartions:
高级数据结构实现——自顶向下伸展树_第2张图片
  • 3.2)inserting opeartions:
高级数据结构实现——自顶向下伸展树_第3张图片

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");
    }
} 

你可能感兴趣的:(数据结构)