Windows 驱动中使用伸展树(Splay Tree)或者平衡树来存储数据,加快数据的查询速度的方法总结。
伸展树
维基百科,自由的百科全书
伸展树(Splay Tree)是一种二叉排序树,它能在O(log n)内完成插入、查找和删除操作。它由Daniel Sleator和Robert Tarjan创造。
它的优势在于不需要记录用于平衡树的冗余信息。
在伸展树上的一般操作都基于伸展操作。
假设想要对一个二叉查找树执行一系列的查找操作。为了使整个查找时间更小,被查频率高的那些条目就应当经常处于靠近树根的位置。于是想到设计一个简 单方法, 在每次查找之后对树进行重构,把被查找的条目搬移到离树根近一些的地方。splay tree应运而生。splay tree是一种自调整形式的二叉查找树,它会沿着从某个节点到树根之间的路径,通过一系列的旋转把这个节点搬移到树根去。
个人总结:这是一种局部最优的思想,是区别于平衡树的平均思想的。。。
AVL树
维基百科,自由的百科全书
非AVL树的例子
同一个树在高度平衡之后的样子
在计算机科学中,AVL树是最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树。查找、插入和删除在平均和最坏情况下都是O(log n)。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。AVL树得名于它的发明者G.M. Adelson-Velsky和E.M. Landis,他们在1962年的论文《An algorithm for the organization of information》中发表了它。
节点的平衡因子是它的右子树的高度减去它的左子树的高度。带有平衡因子1、0或 -1的节点被认为是平衡的。带有平衡因子 -2或2的节点被认为是不平衡的,并需要重新平衡这个树。平衡因子可以直接存储在每个节点中,或从可能存储在节点中的子树高度计算出来。
这里边的处理二叉树的平衡方法:
在驱动初始化的时候,利用RtlInitializeGenericTable初始化相关的信息,这里边包括关联相关的函数:
VOID
RtlInitializeGenericTable(
__out PRTL_GENERIC_TABLE Table,
__in PRTL_GENERIC_COMPARE_ROUTINE CompareRoutine,
__in PRTL_GENERIC_ALLOCATE_ROUTINE AllocateRoutine,
__in PRTL_GENERIC_FREE_ROUTINE FreeRoutine,
__in_opt PVOID TableContext
);
第一个参数,是一个已经分配了存储空间的指针,一般而言,我们都是利用后配列表对其进行分配空间的。
最后一个参数一般:NULL
第二个到第四个参数是我们要注册的函数:
RTL_GENERIC_COMPARE_RESULTS
RoutineName (
__in struct _RTL_GENERIC_TABLE *Table,
__in PVOID FirstStruct,
__in PVOID SecondStruct
);
PVOID
RoutineName (
__in struct _RTL_GENERIC_TABLE *Table,
__in CLONG ByteSize
);
VOID
RoutineName (
__in struct _RTL_GENERIC_TABLE *Table,
__in PVOID Buffer
);
在使用这一系列的函数时,具体参看WDK即可,但是,需要说明的是,对AVL以及伸展树的实现原理应该清楚。