BST就是二叉检索树,或者是二叉排序树,或者叫二叉搜索树等等。
BST的平衡问题可以去学习AVL树或者Treap或者Splay这些平衡树。
BST的一些高级应用:
1,求BST中比k小的数的个数:
只需在BST上面多维护值size,表示当前这个节点的子树的点的个数。
伪代码如下:
1 BST tree; 2 3 int getCou(int k) { 4 Node * u=tree.root; 5 int ret=0; 6 7 while(u!=NULL) { 8 if(u->val<k) { // 如果当前节点值小于k,那么左子树也符合。 9 ret+=1+size(u->left); 10 u=u->right; 11 } 12 else u=u->left; // 如果大于等于k的话,右子树一定不符合。 13 } 14 15 return ret; 16 }
复杂度是logN的。
2,求BST中第x小的数是几?
仍然需要维护size数组。
如果左子树点的个数超过x了,说明第x个在左子树,否则在右子树。
1 BST tree; 2 3 int getXth(int x) { 4 Node * u=tree.root; 5 6 while(u!=NULL) { 7 if(size(u->left)<x) { // 如果左子树个数不足x,递归找右子树。 8 x-=size(u->left)+1; // 递归时在x要变化。 9 if(x==0) return u; // 找到了。 10 11 u=u->right; 12 } 13 else u=u->left; // 递归找左子树。 14 } 15 16 return -1; 17 }
复杂度logN。
3,找到BST中正好比k大的第一个数:
仍然是从root开始找。
代码如下:
1 BST tree; 2 3 int find(int k) { 4 Node * u=tree.root; 5 int ret=INF; 6 7 while(u!=NULL) { 8 if(u->val>k) { // 如果当前节点大,那么他的右子树都比当前节点大,答案一定不如当前节点的值优。 9 ret=min(ret,u->val); 10 u=u->left; 11 } 12 else u=u->right; // 左子树都小,都不符合,所以找右子树去。 13 } 14 15 return ret; 16 }
复杂度 logN 。