特点
1.若任意结点的左子树不空,则左子树上所有结点的值均不大于它的根结点的值。
2. 若任意结点的右子树不空,则右子树上所有结点的值均不小于它的根结点的值。
3.任意结点的左、右子树也分别为二叉搜索树
就如这棵树 假设数列是{12,5,18,2,9,15,19,17,16}
先拿出12作为根节点
再拿出5 发现比12小 就放在左子结点
再拿18 发现比12大就放在右子结点
再拿2 先与12比较 发现比12小 就再与12的左节点比较 发现比5小 就放在5的左子结点
再拿9 先与12比较 发现比12小 就再与12的左节点比较 发现比5大 就放在5的右结点
注意17的位置 他跟18比较 发现比18小就和18的左节点比较 发现比15大 此时不会挤掉15 而是放在15的右结点
如果用中序遍历就会看到一个 递增序列
代码实现
/*先创建二叉树结构体*/
typedef struct treenode /*二叉排序树的结点类型*/
{
KeyType key; /*关键字*/
struct treenode* lchild, * rchild; /*左、右孩子指针*/
}BTNode,*BTree;
/* BTree tree 等价于 BTNode * node 这里写*BTree主要是指向根节点 方便遍历*/
BTNode* NewNode(int data) //创建一个新的节点
{
BTNode* New = (BTNode*)malloc(sizeof(BTNode));//给新节点分配空间
if (nullptr == New)
{
exit(0);
}
New->key = data;//将值赋值给新节点
New->lchild = nullptr;//将左右子结点设置为空
New->rchild = nullptr;
return New;//返回新节点的地址
}
void DispBStree(BTNode* bt)
{ /*用广义表显示二叉排序树函数*///应该是用中序遍历显示一个有序数列
if (NULL != bt)
{
DispBStree(bt->lchild);
printf("%d ", bt->key);
DispBStree(bt->rchild);
}
}
/*bst是根节点 key是要查找的目标值 f是啥 p是最终返回的指针 如果找到了 就返回结点指针 如果没找到 就返回叶子节点的位置 方便插入新节点*/
bool Search(BTree bst, KeyType key, BTree f, BTree* p) //查找成功时,p指向值为key的节点。如果查找失败,则p指向遍历的最后一个节点
{
if (!bst)
{
*p = f;
return false;
}
if (bst->key == key) //查找成功,直接返回
{
*p = bst;//如果找到了 则返回结点指针
return true;
}
else if (bst->key < key)//如果查找值大于结点值 则找右结点
{
return Search(bst->rchild, key, bst, p);
}
return Search(bst->lchild, key, bst, p);//如果查找值小于结点则查找左节点
}
BTNode* BSTInsert(BTNode* bst, KeyType key)
{ /*二叉排序树的元素插入函数*/
if (bst->key == NULL) //首先判断这棵树是不是一个空树 如果是空树就创建结点
{
bst = NewNode(key);
return bst;//返回根节点地址 结束插入
}
/*如果不是空树*/
BTNode* p;
//先在二叉排序树中查找要插入的值是否已经存在
if (!Search(bst, key, NULL, &p)) //如果要插入的值不在,则插入;此时p一定指向遍历的最后一个叶子节点
{
BTNode* pNew = NewNode(key);//创建一个新节点
if (key < p->key) //将s作为p的左孩子
{
p->lchild = pNew;
}
else if (key > p->key) //将s作为p的右孩子
{
p->rchild = pNew;
}
return bst; //插入成功
}
else
{
printf("\nThe node(%d) already exists.\n", key);
}
return bst;
}
BTNode* CreateBST(KeyType str[], int n)
{ /*建立二叉排序树函数*/
BTNode* root = new BTNode;
root = NewNode(str[0]);
for (int i = 1;i<n;i++)
{
BSTInsert(root, str[i]);
}
return root;
}
int Delete(BTree* p)
{
BTree q, s;
//情况 1,结点 p 本身为叶子结点,直接删除即可
if (!(*p)->lchild && !(*p)->rchild) {
*p = NULL;
}
else if (!(*p)->lchild) { //左子树为空,只需用结点 p 的右子树根结点代替结点 p 即可;
q = *p;
*p = (*p)->rchild;
free(q);
}
else if (!(*p)->rchild) {//右子树为空,只需用结点 p 的左子树根结点代替结点 p 即可;
q = *p;
*p = (*p)->lchild;//这里不是指针 *p 指向左子树,而是将左子树存储的结点的地址赋值给指针变量 p
free(q);
}
else {//左右子树均不为空,采用第 2 种方式
q = *p;
s = (*p)->lchild;
//遍历,找到结点 p 的直接前驱
while (s->rchild)
{
q = s;
s = s->rchild;
}
//直接改变结点 p 的值
(*p)->key = s->key;
//判断结点 p 的左子树 s 是否有右子树,分为两种情况讨论
if (q != *p) {
q->rchild = s->lchild;//若有,则在删除直接前驱结点的同时,令前驱的左孩子结点改为 q 指向结点的孩子结点
}
else {
q->lchild = s->lchild;//否则,直接将左子树上移即可
}
free(s);
}
return true;
}
BTNode* BSTDelete(BTNode* bt, KeyType k)
{ /*在二叉排序树t中删除关键字为k的节点函数*/
if (!bt) {//不存在关键字等于key的数据元素
return bt;
}
else
{
if (k == bt->key) {
Delete(&bt);
return bt;
}
else if (k < bt->key) {
//使用递归的方式
return BSTDelete(bt->lchild, k);
}
else {
return BSTDelete(bt->rchild, k);
}
}
}
BTNode* BSTSearch(BTNode* bt, KeyType k)//如果没找到怎么办
{ /*二叉排序树的元素查找函数*/
if (nullptr == bt)//如果查找的是空树直接结束
{
return nullptr;
}
if (bt->key == k)//如果当前结点的值是要找的值 则返回当前结点
{
return bt;
}
else if (nullptr != bt->lchild)//如果左节点不为空 则对左节点进行对比
{
BSTSearch(bt->lchild, k);
}
else if (nullptr != bt->rchild)//如果右结点不为空 则对右结点进行对比
{
BSTSearch(bt->rchild, k);
}
}