调Splay太恐怖了,虽然不难,但是为什么bug这么多。。。这里记一下原则性问题吧。。。
类名叫SplayTree
1 2 3 | int v,size; //分别是键值,子树大小, bool pl; //place 表示该节点在父节点的哪个位置 ST *pr,*suc[ 2 ],*Nil; //分别表示前驱,两个后继,和Nil节点的位置 |
1 2 3 4 5 6 7 8 9 10 11 | /*由于SpayTree太长了,一下所写为ST*/ void mt(); //maintain 即维护Splay,保证信息的正确性 void ini(); //初始化,将所有的前驱后继都改成Nil void trans(ST *tar, bool place); //将该子树移动到tar的place边(place=0表示左子树,反之右子树) void rotate(); //旋转,一个函数搞定左旋/右旋 void Splay(); //核心操作,即将某节点提到根 ST *find_v( int fv) //找到fv所在的位置,找不到返回它应该在的位置的根(按照数字值查询) void insert( int iv /*也可以是 ST*p */ ); //插入iv到相应位置 void find_s( int pos); //按照size找第pos小的元素,也就是如果要求第pos小的元素是哪个,就可以用这个函数在O(lgn)的时间复杂度内完成 ST *fmin /*或fmax*/ (); //找到最小值所在的位置(返回指针) void merge(ST *obj); //将obj所在的Splay合并到该节点所在的Splay... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | void trans(ST *tar,bool place){ //ST::移形换位 pl=place; pr=tar; tar->suc[pl]= this ; } void rotate(){ //旋转 bool ppl=pl; ST fprev=*pr; suc[!pl]->trans(pr,pl); //移动子树 pr->trans( this ,!pl); //移动原前驱 trans(fprev.pr,fprev.pl); //移动该节点 suc[!ppl]->mt(); mt(); } void Splay(){ //Splay操作 while (pr!=Nil){ if (pl==pr->pl && pr->pr!=Nil) pr->rotate(); rotate(); } } |
今天早上。。出于某种不可抗拒的原因,没心情写题,所以正好小记以下(我是按分类记录,不是按日期记录):