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

【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");
    }
} 
时间: 2024-08-08 05:20:32

高级数据结构实现——自顶向下伸展树的相关文章

第12章 高级数据结构及其实现

自顶向下伸展树 1 // SplayTree class 2 // 3 // CONSTRUCTION: with no initializer 4 // 5 // ******************PUBLIC OPERATIONS********************* 6 // void insert( x ) --> Insert x 7 // void remove( x ) --> Remove x 8 // boolean contains( x ) --> Retur

数据结构-伸展树

声明:本文是对某高中生的竞赛论文学习的文章 介绍: 二叉查找树能够支持多种动态集合操作.对于一个含有n个结点的完全二叉树,这些操作的最还情况运行时间是O(lgn),但如果树是含有n个结点的线性链,则这些操作的最坏情况运行时间为O(n).而像红黑树.AVL树这种二叉查找树的变形在最坏情况下,仍能保持较好性能. 本文将要介绍的伸展树也是二叉查找树的变形,它对空间要求及编程难度的要求相对不高. 伸展树: 伸展树与二叉查找树一样,具有有序性.即伸展树的每一个结点x满足:该结点的左子树中的每个元素都小于x

自顶向下的伸展树

一 伸展树的性质 伸展树保证从控制开始任意连续M次对树的操作最多花费O(MlogN)时间,一棵伸展树每次操作的摊还(amortized)代价是O(logN).伸展树的基本思想是,当一个节点被访问后,它就要经过一系列旋转操作被推到根上.另外,伸展树还不要求保留高度或平衡信息. 二 伸展树的伸展操作 在自底向上的伸展操作的直接实现需要从根沿树往下的一次遍历,以及而后的自底向上的一次遍历.这可以通过保存一些父链来完成,也可以通过将访问路径存储到栈中来完成.但是,这两种方法均需大量的开销,而且两者都必须

数据结构之伸展树

1. 概述 二叉查找树(Binary Search Tree,也叫二叉排序树,即Binary Sort Tree)能够支持多种动态集合操作,它可以用来表示有序集合.建立索引等,因而在实际应用中,二叉排序树是一种非常重要的数据结构. 从算法复杂度角度考虑,我们知道,作用于二叉查找树上的基本操作(如查找,插入等)的时间复杂度与树的高度成正比.对一个含n个节点的完全二叉树,这些操作的最坏情况运行时间为O(log n).但如果因为频繁的删除和插入操作,导致树退化成一个n个节点的线性链(此时即为一个单链表

高级数据结构:优先队列、图、前缀树、分段树以及树状数组详解

优秀的算法往往取决于你采用哪种数据结构,除了常规数据结构,日常更多也会遇到高级的数据结构,实现要比那些常用的数据结构要复杂得多,这些高级的数据结构能够让你在处理一些复杂问题的过程中多拥有一把利器.同时,掌握好它们的性质以及所适用的场合,在分析问题的时候回归本质,很多题目都能迎刃而解了. 这篇文章将重点介绍几种高级的数据结构,它们是:优先队列.图.前缀树.分段树以及树状数组. 一.优先队列 1.优先队列的作用 优先队列最大的作用是能保证每次取出的元素都是队列中优先级别最高的,这个优先级别可以是自定

查找——清晰图解伸展树SplayTree

伸展树 伸展树(Splay Tree),也叫分裂树,是一种二叉排序树,它由Daniel Sleator和Robert Tarjan创造,后者对其进行了改进. 假设想要对一个二叉查找树执行一系列的查找操作.为了使整个查找时间更小,被查频率高的那些条目就应当经常处于靠近树根的位置.于是想到设计一个简单方法,在每次查找之后对树进行重构,把被查找的条目搬移到离树根近一些的地方.splaytree应运而生.splaytree是一种自调整形式的二叉查找树,它会沿着从某个节点到树根之间的路径,通过一系列的旋转

高级数据结构

数据结构清单 Binomial Heap Leftist Tree:左倾堆 ? 重型网络教程 1.纸上谈兵:算法与数据结构 2.CS 598 JGE:Advanced Data Structures(Fall 2015) 3.COP 5536 Advanced Data Structures(Florida) 4.wikibooks Data Structures 5.Geeksforgeeks(very much) 6.COMP 5408:Advanced Data Struestures 7

PHP算法 《树形结构》 之 伸展树(1) - 基本概念

伸展树的介绍 1.出处:http://www.cnblogs.com/skywang12345/p/3604238.html 伸展树(Splay Tree)是一种二叉排序树,它能在O(log n)内完成插入.查找和删除操作.它由Daniel Sleator和Robert Tarjan创造.(01) 伸展树属于二叉查找树,即它具有和二叉查找树一样的性质:假设x为树中的任意一个结点,x节点包含关键字key,节点x的key值记为key[x].如果y是x的左子树中的一个结点,则key[y] <= key

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

这是我第一篇对高级数据结构的描述,如有不准确的地方还请指出,谢谢~ 调这颗树的代码调的头皮发麻,和线段树根本不是一个难度的. 首先简单地介绍一下这棵平衡BST中的另类 这是一棵没有任何平衡因子的BST,它依靠均摊来达到O(logn)的插入查询和删除复杂度,常数比较大 而且,它的具有其他BST所不具备的,对于子树的任意分裂和合并的功能 下面我从定义讲起,剖析这棵树实现过程中的每一个细节 const int INF=1000000000; const int maxn=1000005; int n,