查找
静态查找
1.顺序查找 (n)
2.二分查找 (log n)
3.哈希
动态查找
二叉查找树BST(Binary Search Tree)
二叉查找树
二叉查找树又称二叉排序树
定义
空树或者是具有如下特性的二叉树:
1.若它的左子树不空,则左子树上所有结点的值均小于根结点的值;
2.它的右子树不空,则右子树上所有结点的值均大于根结点的值;
3.它的左、右子树也都分别是二叉查找树。
初始化
struct NOTE
{
int l,r,key,val;
}
查找
找最值
这里只列举找最大值的方法,找最小值类似。
迭代方法
void findMax()
{
int now=1;
while(t[t[now].r].val!=-1) //及判断树的右节点是否有值
{
now=t[now].r;
}
return t[now].val;
}
递归方式
void findMax(int now)
{
if(t[t[now].r].val!=-1)
{
findMax(t[now].r);
}
else return t[now].val;
}
查找比x大(小)的最小(大)值
比x小的最大值。
迭代方法
int findMinm(int w)
{
int x=root;
int y=0;
while (x!=-1)
if (t[x].val<w)
{
y=t[x].val;
x=t[x].r;
}
else x=t[x].l;
return y;
}
插入
把X插入树T中,像Find那样沿着树找。如果找到X,则什么也不用做(或做一些更新),否则将X插入到遍历的路径上最后一个结点上,新插入的结点一定是叶子结点(只需改动一个结点的指针),该叶子结点是查找不成功时路径上访问的最后一个结点左孩子或右孩子(新结点值小于或大于该结点值)
但是如果只是这么做很有可能会超时,因为平衡树有可能会退化成O(n),准确来说是很有可能。
然后我们就可以给节点随机分配一个优先级,先和二叉搜索树的插入一样,先把要插入的点插入到一个叶子上,然后跟维护堆一样,如果当前节点的优先级比根大就旋转,如果当前节点是根的左儿子就右旋如果当前节点是根的右儿子就左旋。
由于旋转是O(1)的,最多进行h次(h是树的高度),插入的复杂度是O(h)的,在期望情况下h=O(log n),所以它的期望复杂度是O(log n)。
于是得到了以下代码
void rttr(int &dep)
{
int y=t[dep].l;
t[dep].l=t[y].r;
t[y].r=dep;
dep=y;
}
void rttl(int &dep)
{
int y=t[dep].r;
t[dep].r=t[y].l;
t[y].l=dep;
dep=y;
}
void insert(int &dep,ll x)
{
if(!dep)
{
dep=++tot;
t[tot].val=x;
t[tot].key=rand();
return ;
}
if(t[dep].val==x)
return ;
if(t[dep].val>x)
{
insert(t[dep].l,x);
if(t[t[dep].l].key<t[dep].key)
rttr(dep);
}
else
{
insert(t[dep].r,x);
if(t[t[dep].r].key<t[dep].key)
rttl(dep);
}
}
习题
bzoj 3544: [ONTAK2010]Creative Accounting treap
blog http://blog.csdn.net/qq_33229466/article/details/53614337
set
http://hzwer.com/6391.html