1、什么是二叉查找树
二叉查找树就是空树或者是每一个结点都有作为查找的依据,并且所有的做左子树的依据都比根结点的小,所有右子树的依据都比根结点的小
这就是一棵二叉查找树
同时我们可以看到假如对一棵这样的树进行中序遍历时,可以发现所有依据都将按照从小到大排名
中序遍历:1 3 4 6 7 8 10 13 14
同时我们也可以看到最左的结点的依据是最小的,最右的结点是最大的
2、如何构建?
1)数据类型
其实就是二叉树加上个依据而已
typedef struct {int key;} ElemType;
typedef struct BitTNode
{
ElemType data;
struct BitTNode *lchild, *rchild;
}BitTNode, *BitTree;
2)如何构建呢?
从空树出发,依次插入数据
(1)如果是空树则插入结点就是二叉查找树的根结点
(2)如果非空,则插入值与根结点比较,若小于根结点则进入左子树,若大于则进入右子树,递归比较。
对于一棵二叉查找树最重要的是查找,查找就是按照二叉树的定义查找
有了查找算法后我们可以定义插入算法,有以结点方式插入,有以依据方式插入
// Insert node
void Insert_BitTree_1(BitTree &T, BitTree S)
{
BitTree p; //use to find the place to insert
BitTree q; //use to store the parent
if(!T) T=S; //空树直接插入
else
{
p=T;
while(p)
{
q=p; //记录父母
if(S->data.key < p->data.key)
{
p=p->lchild;
}
else p=p->rchild;
}
if(S->data.key < q->data.key)
q->lchild = S;
else
q->rchild = S;
}
}
// Insert node
void Insert_BitTree_2(BitTree &T, int key)
{
BItTree p;
BitTree q;
BitTree S = new BitTNode();
if(!T) //空结点
{
S->data.key = key;
S->lchild = NULL;
S->rchild = NULL;
T=S;
}
else
{
p = T;
while(p)
{
q=p;
if(key > p->data.key)
{
p=p->rchild;
}
else p=p->lchild;
}
if(q->data.key < key)
{
S->data = key;
S->lchild = NULL;
S->rchild = NULL;
q->rchild = S;
}
else
{
S->data.key = key;
S->lchild = NULL;
S->rchild = NULL;
q->lchild = S;
}
}
}
有插入之后我们需要删除
删除二叉查找树有两种情况
一、删除叶子结点
直接删除
二、删除根结点
(1)如果有两个孩子
选择根结点的左子树中最大的结点作为新的根结点
或者选择根结点的右子树最小的结点作为新的根结点
(2)如果只有一个孩子
则直接把他的孩子作为根结点
void Delete_BST(BitTree &T, int key)
{
BitTree p, f;
p = T; //p为要删除的结点
f = NULL; //用f储存要删除的结点的父母
while(p)
{
if(p->data.key == key)
{
delNode(T, p ,f); // 找到要删除的结点,传入删除函数进行删除
}
else if(p->data.key < key)
{
f=p;
p=p->rchild;
}
else if(p->data.key>key)
{
f=p;
p=p->lchild;
}
}
}
void delNode(BitTree &T, BitTree p, BitTree f)
{
BitTree s, q; //用s储存要删除的结点的孩子结点
int tag;
tag=0;
if(!p->lchild) s=p->rchild; //没有左孩子则记录右孩子
else if(!p->rchild) s=p->lchild; //没有右孩子则记录左孩子
else // 有两个孩子
{
//要找左子树中最大的结点做根
q=p;
s=p->lchild;
while(s->rchild)
{
q=s; //s储存要做根的结点,q储存s的父母
s=s->rchild;
}
p->data=s->data;
if(q==p)q->lchild=s->lchild;
else q->rchild=s->lchild;
delete s;
tag=1;
}
if(!tag) //有1个孩子
{
if(!f)T=s; //删除的是根结点
else if(f->lchild==p)f->lchild=s;
else f->rchild=s;
delete p;
}
}