#include "stdafx.h"
#include <iostream.h>
#include <malloc.h>

typedef struct btnode * bitreptr;

struct btnode


{
int data; //数据
bitreptr lchild; //左节点指针
bitreptr rchild; //右节点指针
};

//建立一个新结点
bitreptr CreateNewNode(int data)


{
bitreptr node=(bitreptr)malloc(sizeof(btnode));
node->data=data;
node->lchild=NULL;
node->rchild=NULL;
return node;
}

//中根遍历
void inorder(const bitreptr root)


{
bitreptr node=root;
if (node!=NULL)

{
inorder(node->lchild);
cout<<node->data<<endl;
inorder(node->rchild);
}
}
//建立P135的图6-2的图
bitreptr CreateStaticBinTree()


{
bitreptr node37=CreateNewNode(37);

bitreptr node21=CreateNewNode(21);
node37->lchild=node21;
bitreptr node6=CreateNewNode(6);
node21->lchild=node6;
bitreptr node32=CreateNewNode(32);
node21->rchild=node32;
bitreptr node23=CreateNewNode(23);
node32->lchild=node23;
bitreptr node33=CreateNewNode(33);
node32->rchild=node33;

bitreptr node51=CreateNewNode(51);
node37->rchild=node51;
bitreptr node86=CreateNewNode(86);
node51->rchild=node86;
bitreptr node60=CreateNewNode(60);
node86->lchild=node60;
bitreptr node65=CreateNewNode(65);
node60->rchild=node65;

return node37;
}

//在二叉排序树上进行查找
bitreptr search_bst(bitreptr node,int key)


{
if (node==NULL)

{
return NULL;
}
else if (key==node->data)

{
cout<<"匹配"<<endl;
return node;
}
else if (key>node->data)

{
bitreptr tmp=search_bst(node->rchild,key);
cout<<"返回"<<endl;
return tmp;
}
else if (key<node->data)

{
bitreptr tmp=search_bst(node->lchild,key);
cout<<"返回"<<endl;
return tmp;
}
}

//书上的二叉排序树的插入算法,做了一点修改,书上的算法只能确保要么存在,要么插入,我加了一个参数,记录一下找到的结点

//此算法精妙之处在于递归算法的实现,像node->rchild=insert_bst(node->rchild,key);return node;这样的,如果匹配成功则
//将此结点返回,那么返回到上层的递归调用时只是做了一些赋值;如果匹配不成功,则创建了一个新结点,然后返回后链接到上次
//调用的结点的相应指针域上.此算法唯一浪费的就是赋值操作的浪费,因为每递归调用一次在返回时都将做一次赋操作,另外,在
//二叉排序树的整体算法中,包括查找,插入,删除其实都可以遵寻同一个方式,就此书上的两个例子而言,查找和插入的算法还是很
//相似的,但是如果在此基础上做删除操作,就不能按这样的递归方式,因为在递归时候没有记录相关的信息,相比之下,严蔚敏版的
//数据结构的算法记录了相关的信息,使其查找,插入,删除操作可以按同一思路进行,容易理解消化.
bitreptr insert_bst(bitreptr node,int key,bitreptr & findnode)


{
if (node==NULL)

{
findnode=CreateNewNode(key);
return findnode;
}
else if (key==node->data)

{
findnode=node;
return node;
}
else if (key>node->data)

{
node->rchild=insert_bst(node->rchild,key,findnode);
return node;
}
else if (key<node->data)

{
node->rchild=insert_bst(node->lchild,key,findnode);
return node;
}
}
//严蔚敏版对二叉排序树的实现
//node:初始结点 key:查找的关键字值 parent:node的双亲 findnode:找到的结点或新增的结点
void Yan_insert_bst(bitreptr node,int key,bitreptr parent,bitreptr & findnode)


{
if (node==NULL)

{
findnode=CreateNewNode(key);
if (parent!=NULL)

{
if (parent->data<key)

{
parent->rchild=findnode;
}
else

{
parent->lchild=findnode;
}
}
}
else if (key==node->data)

{
findnode=node;
return;
}
else if (key>node->data)

{
Yan_insert_bst(node->rchild,key,node,findnode);
return;
}
else if (key<node->data)

{
Yan_insert_bst(node->lchild,key,node,findnode);
return;
}
}
//删除
void Delete_bst(bitreptr node,int key,bitreptr parent,bitreptr & findnode)


{
if (node==NULL)

{
findnode=NULL;
return;
}
else if (key==node->data)

{
//分4种情况处理
//1.页子结点直接删除
if (node->lchild==NULL && node->rchild==NULL)

{
if (parent!=NULL)

{
if (parent->data>node->data)

{
parent->lchild=NULL;
}
else

{
parent->rchild=NULL;
}
}
free(node);
node=NULL;
}
//2.右子树为空,则直接连接左子树
else if (node->rchild==NULL)

{
bitreptr tmp=node;
node=node->lchild;
free(tmp);
tmp=NULL;
}
//3.左子树为空,则直接连接右子树
else if (node->lchild==NULL)

{
bitreptr tmp=node;
node=node->rchild;
free(tmp);
tmp=NULL;
}
//4.待删结点的有左右子树的删除算法,书上讲的不是很清楚,我在这里说一下,其思路是,其右子树的相对位置不会改变,在待删结点的左
//子树上找最大的结点,替换掉这个待删结点.那么,因为其左子树也是二叉排序树,所以这个左子树上的最大结点也就是其待删结点的左子
//树上的首节点的右子树上的最后一个其rchild为NULL的结点.然后将这个结点的左子树挂到它的父结点的右子树结点上,将这个结点的左/右
//指向待删结点的左/右结点上.修改其它待删结点的父结点,指向这个新的结点.
//其中,有一个特例,就是这个待删结点的左子树的首节点,其右子树为空,那么此时只需要将这个左子树挂到这个待删结点上就可以了.
else

{
bitreptr leftnode=node->lchild;
if (leftnode->rchild==NULL)

{
//此待删除结点的左子树首结点不存在右子树的情况,则直接将此左子树挂接到待删处
bitreptr tmp=node;
node=node->lchild;
free(tmp);
tmp=NULL;
}
else

{
bitreptr rightnode=leftnode->rchild;
bitreptr rightparent=leftnode;
//找到右子树最大的
while(rightnode->rchild!=NULL)

{
rightparent=rightnode;
rightnode=rightnode->rchild;
}
//将右子树中最大结点的左子树挂接到其父结点的右子树上
rightparent->rchild=rightnode->lchild;
//修改此结点的左子树指向待删结点的左子树,右结点指向待删结点的右子树
rightnode->lchild=node->lchild;
rightnode->rchild=node->rchild;
bitreptr tmp=node;
node=rightnode;
free(tmp);
}
}
if (parent->data>node->data)

{
parent->lchild=node;
}
else

{
parent->rchild=node;
}
return;
}
else if (key>node->data)

{
Delete_bst(node->rchild,key,node,findnode);
return;
}
else if (key<node->data)

{
Delete_bst(node->lchild,key,node,findnode);
return;
}
}
int main(int argc, char* argv[])


{
//1.测试静态二叉排序树上的查找算法
bitreptr tree=CreateStaticBinTree();
cout<<"建立二叉树的结点为:"<<endl;
inorder(tree);
bitreptr findnode=search_bst(tree,65);
if (findnode!=NULL)

{
cout<<"findnode="<<findnode->data<<endl;
}
//2.测试书上的二叉排序树的插入算法
findnode=NULL;
insert_bst(tree,86,findnode);
cout<<"测试使用书上算法插入一个现存的结点:"<<findnode->data<<endl;
cout<<"当前结点为:"<<endl;
inorder(tree);
findnode=NULL;
insert_bst(tree,88,findnode);
cout<<"测试使用书上算法插入一个不存在的结点:"<<findnode->data<<endl;
cout<<"当前结点为:"<<endl;
inorder(tree);
//3.测试严蔚敏版二叉排序树的插入算法
findnode=NULL;
Yan_insert_bst(tree,32,NULL,findnode);
cout<<"测试严蔚敏版的算法插入一个现存的结点:"<<findnode->data<<endl;
cout<<"当前结点为:"<<endl;
inorder(tree);
findnode=NULL;
Yan_insert_bst(tree,34,NULL,findnode);
cout<<"测试严蔚敏版的算法插入一个不现存的结点:"<<findnode->data<<endl;
cout<<"当前结点为:"<<endl;
inorder(tree);
//4.测试删除算法
cout<<"测试删除结点86"<<endl;
findnode=NULL;
Delete_bst(tree,86,NULL,findnode);
cout<<"当前结点为:"<<endl;
inorder(tree);
return 0;
}
一点说明:为什么在标题中要嵌入英文?原因是为了能够让国外的网友能查询到这篇文章。平常在Google上查资料的时候,经常参考国外网友的博客,帮助我解决了很多问题,所以我也想让他们能够参考我写的内容。当然文中我不可能全部译为英文,所以我尽量把代码粘全,靠代码说话吧。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步