lighttpd 之六 伸展树

1.1  概述

       伸展树或者分裂树,由Daniel Sleator和Robert Tarjan创造,它的优势在于不需要记录用于平衡树的冗余信息。

伸展树是一种二叉排序树,它能再O(log n)内完成插入、查找和删除操作。lighttpd源码里关于伸展树的代码不多

(对伸展树的操作只提供了4个函数),但是因为伸展树本身相对比较复杂,因此在此作为一章来解析,对伸展树理

解较深的读者可以直接跳过本章内容。

       本节相关部分源码:

       splaytree.h

       splaytree.c

1.2 伸展树基础知识

1.2.1 伸展树介绍

        假想这么一种情况,我们想要对一个二叉查找树执行一系列的查找操作,后续会在缓存器设计中看到,为了使整个

查找时间更短,哪些查评率比较高的节点就应该经常处于比较靠近树根的位置,于是最直观的想法就是将每次查找访问节

点之后对该树进行重构,将被查找的节点搬移到树根,这种自调整形式的二叉查找树就是伸展树,他会沿着从某个被访问

节点到树根之间的路径,通过一系列的旋转把这个被访问节点搬移到树根。

        伸展树通过一系列的旋转把当前被访问节点搬移到树根,以便下次再次访问该节点时加快速度(直接访问根节点就被命

中或离树根很近的位置)。为了将当前被访问节点搬移到树根,我们需要将沿着查找路径做自底向上的旋转,直至该节点为

树根为止(伸展树定义的旋转是成对进行的,伸展操作不单是把当前访问节点搬移到树根,而且还把查找路径上的每个节点

的深度都大致减掉一半)。

    参考博客https://blog.csdn.net/mu0206mu/article/details/70185944

1.3  lighttpd中伸展树实现源码解析

1.3.1 结构定义

       伸展树的数据结构定义在对应的splaytree.c 头文件内,结构如清单 

typedef struct tree_node {
    struct tree_node * left, * right;
    int key;

    /*记录该节点下有多少个子孙节点(并把自己也计算在内)*/
    int size;   /* maintained to be the number of nodes rooted here */

    void *data;
} splay_tree;

     splaytree.h头文件内还有一个计算节点大小(即size字段值)的宏,正如lighttpd开发者注释的那样,该宏比直接使用

x->size更好

1.3.2 函数操作

1.splay_tree * splaytree_splay (splay_tree *t, int key);

       该函数实现伸展树的伸展操作(采用的是自顶向下且简化实现方式),函数在伸展树t中查找t->key等于key的节点(当然在查找的过程中会进行伸展操作,同时为保证size元素的正确要对其进行更新),如果找到则返回改节点(该节点经过伸展后变成根节点),否则返回空。

 2.splay_tree * splaytree_insert(splay_tree *t, int key, void *data);

        该函数首先在伸展树t中查找t->key为key的节点,如果找到则直接返回该节点,函数结束;否则新建立一个节点,其t->key

为key,附加数据由参数data指针提供,然后将该节点作为新根节点插入伸展树t并作为返回值返回。

3.splay_tree * splaytree_delete(splay_tree *t, int key);

         该函数从伸展树t中删除t-key为key的节点(如果该节点存在)。

4.splay_tree * splaytree_size(splay_tree *t);

        该函数返回伸展树的节点数目

参考文档 lighttpd源码分析 高群凯著

          下载路径:https://download.csdn.net/download/caofengtao1314/10576306

猜你喜欢

转载自blog.csdn.net/caofengtao1314/article/details/82834430
今日推荐