二叉查找树学习笔记(BST)
我土了....终于开始看平衡树了,以前因为害怕一直不敢看数据结构...浑浑噩噩跟同学落了1—2个数据结构没看....果然,我是最弱的
二叉查找树,遵守每个点的左儿子小于点小于右儿子。
于是,BST能够支持的操作:
加点(不用说了)
找前驱(小于一个值的最大值)
找后继(大于一个值得最小值)
根据排名找值
根据值找排名。
直接上代码,理解讲解都在注释里(只给各个函数的代码了)
struct tree { int ls,rs,size,cnt,val; }t[maxn]; //以下为加点 //size表示当前节点的子树大小和自己的大小的和, //cnt表示当前节点代表的数有几个 void add(int now,int val)//now为当前遍历的点的编号,val为点权值 { t[now].size++; if(t[now].val==val) { t[now].cnt++;//多个相同值得点,不增加点了 return; } if(t[now].val>val) { if(t[now].ls!=0) { addedge(t[now].ls,val); } else { cnt++; t[cnt].size=1; t[cnt].val=val; t[cnt].cnt=1; t[now].ls=cnt; } } else if(t[now].val<val)//根据二叉查找树的性质来插值 { if(t[now].rs!=0)//如果不是叶子节点 { addedge(t[now].rs,val);//向下寻找叶子节点再插入 } else { cnt++;//cnt为点的编号 t[cnt].size=1;//找前驱的东西 t[cnt].val=val;//存值 t[cnt].cnt=1;//有几个相同的值 t[now].rs=cnt;//点的编号,右儿子加点 } } } int getqianqu(int now,int val,int ans) { if(t[now].val>=val)//如果当前值大于正在被寻找前驱的值 {//那么可以判定:前驱一定是在它的左子树中 if(t[now].ls==0)//如果没有左子树 { return ans;//当前值就是答案 } else //否则 { getqianqu(t[now].ls,val,ans);//在左子树中找答案 } } else if(t[now].val<val)//如果当前值小于正在被寻找前驱的值 {//那么可以判定:前驱一定在它的右子树中 ,一路小过来,小过了,往大值试探 if(t[now].rs==0)//如果没有右子树 { if(t[now].val<val)//如果当前值小于正在被寻找前驱的值 { return t[now].val;//在没有右子树的情况下,当前点就是前驱 } else { return ans;//否则前面点就是前驱 } } if(t[now].cnt!=0)//删点之后..在treap里的操作,这里没有 { return getqianqu(t[now].rs,val,t[now].val); } else { return getqianqu(t[now].rs,val,ans); } } } int gethouji(int now,int val,int ans) { if(t[now].val<=val)//如果当前值大于正在被寻找前驱的值 { if(t[now].rs==0)//如果没有左儿子 { return ans; } else { gethouji(t[now].rs,val,ans); } } else if(t[now].val>val) { if(t[now].ls==0) { if(t[now].val>val) { return t[now].val; } else { return ans; } } if(t[now].cnt!=0) { return gethouji(t[now].ls,val,t[now].val); } else { return gethouji(t[now].ls,val,ans); } } } //size表示当前节点的子树大小和自己的大小的和, //cnt表示当前节点代表的数有几个 int nth(int now,int rank) { if(now==0)//0,没有值 { return 0x7fffffff; } if(t[t[now].ls].size>rank)//如果左子树的子树的大小大于nth { return nth(t[now].ls,rank);//去找左子树 } if(t[t[now].ls].size+t[now].cnt>=rank)//如果左子树的子树的大小+当前节点(重复节点)大于等于nth { return t[now].val;//那这个点就是nth } return nth(t[now].rs,rank-t[t[now].ls].size-t[now].cnt);//找子树中nth-子树大小的值 } int valth(int now,int val) { if(now)==0) { return 0; } if(val==t[now].val) { return t[t[now].ls].size+1; } if(val<t[now].val) { return valth(t[now].ls,val); } return valth(t[now].rs,val)+t[t[now].ls].size+t[now].cnt; }//基本同理于kth
(完)