二叉排序树
二叉排序树(Binary Sort Tree),又称为二叉查找树;它是一棵空树或着是具有下列性质的二叉树:
- 若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
- 若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
- 左、右子树也分别为二叉排序树。
- 不允许有键值相同结点
当我们对上图的二叉排序树进行中序遍历时,便可以得到有序的序列;但构造一个排序二叉树的目的,其实并不是为了排序,而是为了提高查找和插入删除关键字的速度。
二叉排序树的操作
首先提供下二叉树的结构:
typedef struct BTNode
{
int data;
BTNode* lchild;
BTNode* rchild;
}BTNode,*BiTree;
节点查找
二叉排序树的节点查找,就是利用左右孩子和父结点的大小关系来确定查找的方向。
#include <iostream>
typedef struct BTNode
{
int data;
BTNode* lchild;
BTNode* rchild;
}BTNode,*BiTree;
//递归查找
BTNode* SearchBST(BiTree T,int x)
{
if (!T) return NULL;
if (T->data == x) return T;
if (x < T->data) return SearchBST(T->lchild,x);
if (x > T->data) return SearchBST(T->rchild,x);
}
//非递归查找
BTNode* BSTSearch(BiTree T,int x)
{
BiTree p = T;
while (p)
{
if (p->data == x) return p;
p = x > p->data ? p->rchild : p->lchild;
}
return NULL;
}
插入操作
对于一颗二叉排序树来说,如果查找某个元素成功,说明该结点存在;如果查找失败,则查找失败的地方一定就是该结点应该插入的地方。
1. 递归的实现方式:
BiTree InsertBST(BiTree T,int key)
{
if (T == NULL) //T为null时,设置新创建的结点为root结点
{
T = (BiTree)malloc(sizeof(BTNode));
T->data = key;
T->lchild = T->rchild = NULL;
return T;
}
if (key < T->data)
T->lchild = InsertBST(T->lchild,key);
else
T->rchild = InsertBST(T->rchild, key);
return T;
}
2. 非递归的实现方式:
bool BSTInsert(BiTree T, int x)
{
BiTree p = T;
BiTree pre = NULL,s = NULL;
while (p)
{
if (p->data == x) break;
pre = p;
p = x > p->data ? p->rchild : p->lchild;
}
if (p)
{
return false;//结点存在,直接返回
}
else
{
s = (BiTree)malloc(sizeof(BTNode));
s->data = x;
s->lchild = T->rchild = NULL;
if (pre == NULL)
{
T = s;
}
else if (pre->data > x)
{
pre->lchild = s;
}
else
{
pre->rchild = s;
}
}
return true;
}
删除结点操作
对删除结点的分析:
1. 删除的结点为叶子结点:直接删除
2. 删除的结点仅有左或右子树:将左或右子树移动到删除结点位置即可
3. 删除结点既有左子树又有右子树:用比当前结点小的最大结点 或 用比当前结点大的最小结点替换删除结点
bool BSTInsert(BiTree T, int x)
{
BiTree p = T;
BiTree pre = NULL,s = NULL;
while (p)
{
if (p->data == x) break;
pre = p;
p = x > p->data ? p->rchild : p->lchild;
}
if (p)
{
return false;//结点存在,直接返回
}
else
{
s = (BiTree)malloc(sizeof(BTNode));
s->data = x;
s->lchild = T->rchild = NULL;
if (pre == NULL)
{
T = s;
}
else if (pre->data > x)
{
pre->lchild = s;
}
else
{
pre->rchild = s;
}
}
return true;
}
bool Delete(BiTree *p)
{
BiTree q, s;
if ((*p)->rchild == NULL)
{
q = *p;
*p = (*p)->lchild;
free(q);
}
else if( (*p)->lchild == NULL )
{
q = *p;
*p = (*p)->rchild;
free(q);
}
else
{
q = *p;//记录删除结点
s = (*p)->lchild;
//获取小于删除结点的最大值
while (s->rchild)
{
q = s;
s = s->rchild;
}
(*p)->data = s->data;//替换
if (q != *p)
{
q->rchild = s->lchild;
}
else 当删除结点的左子树的根结点只有左子树时执行
{
q->lchild = s->lchild;
}
free(s);
}
return;
}