二叉排序树 (BST)
:
建立在二叉树基础上,性质如下
- 若它的左子树不空,则左子树上所有结点的值均小于它的根结构的值
- 若它的右子树不空,则右子树上所有结点的值均大于它的根结构的值
- 它的左子树和右子树都是二叉排序树
- 故左子树所有结点一定比父结点小,右子树所有结点一定比父结点大
查找,近乎析半查找,输出采用中序遍历,可获取从大到小序列
构造一颗二叉排序树的目的,其实并不是为了排序,而是为了提高查找和插入删除关键字的速度。
代码示例:
创建:输入前序排列的数组
PNODE creatree(PNODE *tr,int a[])
{
//cout<<
inode=c;
n++;
creatree(&(*tr)->left,a);
n++;
creatree(&(*tr)->right,a);
}
}
插入:
int inserttr(PNODE *tr,int a)//注意形参为指针的指针,若PNODE tr的话无法传回tre
{
if(*tr==NULL)
{
*tr=new NODE;
(*tr)->inode=a;//(*tr)加括号
(*tr)->left=NULL;
(*tr)->right=NULL;
}
else{
if((*tr)->inode>a)
{
inserttr(&(*tr)->left,a);
}
else if((*tr)->inode
right,a);
}
}
return 1;
}
该节点若是空,插入即可,
非空,小于该节点值,再插入左子树,否则,插入右子树,等于该节点值,则不执行;并不会引起二叉树其他部分的结构变化
查找:
PNODE* findq(PNODE *tr,int a)//查找不成功返回-1;其他返回1;
{
if((*tr)==NULL)
{
return NULL;
}
else if((*tr)->inode==a)
return tr;
else
{
if((*tr)->inode>a)
{
return findq(&(*tr)->left,a);//层层返回消息
}
else
{
return findq(&(*tr)->right,a);
}
}
}
该节点若是空,返回,
非空,小于该节点值,入左子树查找,大于该节点,入右子树查找,等于该节点,即找到
删除:代码块一直显示empty,不知为啥,只有直接贴出来了;此代码验证无误,有许多博客写的不全面或是错的
int deletetr(PNODE *tr,int a)
{
PNODE *c=(findq(tr,a));
PNODE s,q;
if(c==NULL)
return NULL;
if(((*c)->left!=NULL)&&((*c)->right!=NULL))//被删除节点有左右子树
{
q=*c;
s=(*c)->left;
while((s)->right)//寻找左子树最右节点
{
q=s;
s=(s)->right;
}
(*c)->inode=(s)->inode;//交换被删除节点与最右节点的值,子树指针保留,这样操作比较方便
//最右节点可能存在左子树,将其保留,但注意:
if(q==(*c))//此时,新节点就是被删除节点的左子树根
q->left=s->left;
else
q->right=s->left;
delete s;
}
else if(((*c)->left==NULL)&&((*c)->right==NULL))
{
q=*c;
(*c)=NULL;
delete q;
}
else
{
if((*c)->left!=NULL)
{
q=*c;
(*c)=(*c)->left;
delete q;
}
else
{
q=*c;
(*c)=(*c)->right;
delete q;
}
}
return 1;
}
叶子节点直接删除;
有一个子树上移连接即可;
两个子树,两种方法
1.用被删结点左子树最右下的结点的值代替被删结点的值,然后删去最右下的结点,即直接前驱
2.用被删结点右子树最左下的结点的值代替被删结点的值,然后删去最左下的结点,即直接后继
为啥可以这样?直接前驱或者直接后继,就是数值上最贴近被替换节点的值,故直接替换值即可,被替换节点的左右子树指针不变,注意指针操作
我们采用方法1
主函数:中序遍历函数参见二叉树内容
typedef struct node{
int inode;
node *left;
node *right;
}NODE ,*PNODE;
int main()
{ int a[7]={12,10,'%','%',19,'%','%'};
PNODE tre;
creatree(&tre,a);//前序排列初始化一个树;%表示无节点
midout(tre);//
cout<
结果:
