AVL树:
struct property:BST,满足左节点小于根小于右节点,子树为BST
order property:要求左子树和右子树的高度之差不超过2
高度:空子树高度为-1,1个节点高度为0
插入
1.首先按照BST插入
2.进行调整:
A:高度最低的被破坏的点
B:A的左或右孩子,新插入的点的前辈
C:B的左或右孩子,新插入的点的前辈
相当于从被破坏的点向根,靠近根的三个点,依次为ABC
RRrotation:如果新插的点在A的右右侧(右侧子树的根节点的右侧)或者左左侧,将B作为根,然后调整子树。
LRrotation和RLrotation:如果新插的点在A的右左侧或左右侧,将C作为根调整AB,再连接子树。
高度
高度为h的最小节点数n:左侧节点个数为 n h − 1 n_{h-1} nh−1,右侧节点个数为 n h − 2 n_{h-2} nh−2或者互换,因此递推式为: n h = n h − 1 + n n − 2 + 1 n_h=n_{h-1}+n_{n-2}+1 nh=nh−1+nn−2+1
注意真正算的时候用这个递推关系算就行(因为对于高度的定义不同会出问题)
因此高度为O(log N)
Splay树
每次访问,插入的时候,总是将这个点移动到root。
插入
1.按照正常的BST插入
2.调整A:
如果A父节点是根,取下A和父节点的子树,将A作为根,将父节点作为A的子节点,
如果A父节点和父父节点存在:
LL或者RR(父节点的右侧的节点的右侧是A),那么取下子节点,将A调整到最高的位置,将父节点和父父节点也按照LL或者RR排列,然后将子节点连上去。
LR或者RL(父父节点的右侧是父节点,父节点的左侧是A)那么取下子节点,将A调整到最高位置,将父节点和父父节点放在A的两侧,然后将子节点连上去。
3.删除A:
首先访问A,使得A到达了根,然后直接删除。在左子树找最大的元素,或者右子树找最小的元素作为根。
高度
O(logN)
均摊分析
背景是每一步的操作的复杂度不同,但是复杂度之和是固定的,因此希望能够算每步的复杂度的上界。
worst-case bound>amortized bound>average-case bound
上面的意思是:复杂度最高的上界大于均摊上界大于平均值上界。因为均摊的上界相当于固定长度的步骤复杂度求和再求平均的最大值,肯定比最高复杂度小,但是由于是固定长度步骤中最大复杂度,肯定比平均大。
Aggregate analysis
考虑总和的最坏情况 T ( n ) T(n) T(n)。则每一步的复杂度为 T ( n ) / n T(n)/n T(n)/n
Accounting method
设定一个amortized cost,如果当前步骤所作的复杂度小于amortized cost,则产生了credit,可以付给以后的步骤。
要求设计的时候amorized cost求和必须大于实际支出,则可以根据amortized cost确定每一步复杂度。
Potential method
挑选一个势能函数,势能函数代表了当前累计的credit。比如之前的操作复杂度比均摊复杂度大,那么势能增加。
要求:
1.最后势能减去最开始的势能一定是正数。
2.对于一个操作,如果复杂度大于均摊复杂度,那么势能一定增加了差值。
一个好的势能函数要求在最开始的时候取最小值。