二叉搜索树是能够高效进行如下操作的数据结构:
#插入一个数值
#查询是否包含某个数值
#删除某个数值
二叉搜索树能够高效地管理数的集合。
其上的所有节点,都满足左子树上的所有节点都比自己的小,而右子树上的所有节点都比自己大的这一条件
下面是二叉搜索树的一种实现方法
struct node { int val; node *lch, *rch; }; //插入数值x node *insert(node *p, int x) { if (p==NULL) { node *q = new node; q->val = x; q->lch = q->rch = NULL; return q; } else { if(x<p->val) p->lch = insert(p->lch, x); /*递归插入左子树*/ else p->rch = insert(p->rch, x); /*递归插入右子树*/ return p; } } //查找数值x bool find(node *p, int x) { while (p) { if (x>p->val) p = p->rch; else if (x<p->val) p = p->lch; else return true; } return false; } //删除数值x node *remove(node *p, int x) { if(p==NULL) return NULL; else if (x < p->val) p->lch = remove(p->lch, x); /* 从左子树递归删除 */ else if (x > p->val) p->rch = remove(p->rch, x); /* 从右子树递归删除 */ else if (p->lch==NULL) { node *q = p->rch; delete p;//释放内存(实际意思是指删除了p所指的对像,释放了它所占的堆空间,但其本身仍然存在) return q; } else if (p->lch->rch==NULL) { node *q = p->lch; q->rch = p->rch; delete p; return q; } else { node *q; for (q = p->lch; q->rch->rch!=NULL; q = q->rch); node *r = q->rch; q->rch = r->lch; r->lch = p->lch; r->lch = p->rch; delete p; return r; } return p; }
附:二叉搜索树的删除可能稍微麻烦一点,需分以下几种情况进行处理:
#需要删除的节点没有左儿子,那么就把右儿子提上去
#需要删除的节点的左儿子没有右儿子,那么就把左儿子提上去
#以上两种情况都不满足的话,就把左儿子的子孙中最大的节点提到需要删除的节点上
(之所以会有这几种情况,按我的想法来说,开始的时候可以将这棵树看作是满二叉树,那么要进行删除操作的话只需就把左儿子的子孙中最大的节点提到需要删除的节点上即可。但是 q->rch->rch!=NULL 相关操作会导致,如果出现需要删除的节点的左儿子没有右儿子的这种情况,访问就会越界,因此就有了第二种情况。最后整体再优化一下,不是所有的二叉树都要进行复杂的操作,对有些情况可以进行简单处理,于是就有了第一种情况)