您的位置:首页 > 其它

二叉排序树(Binary Sort Tree)

2015-09-21 16:06 253 查看
参考文章:http://blog.csdn.net/ns_code/article/details/19823463

不过博主的使用第一种方法操作后的树已经不是二叉排序树了,值得深思!!

#include "stdio.h"
#include "stdlib.h"

//二叉链表结点
typedef struct Node{
int data;
struct Node *lchild,*rchild;
}Node,*BSTree;

/*
在指针pTree所指的二叉排序树中递归查找关键字为key的元素,
若查找成功,则返回ture,并将 查找到的数据对应的节点指针 保存在p中,
否则返回0,并将 查找路径上访问的最后一个节点指针 保存在p中。
这里的参数f指向每次递归遍历的子树的根节点的父节点,即始终是参数pTree的父节点,
它的初始值为NULL,其目的是跟踪查找路径上访问的当前节点的父节点(即上一个访问节点)
该函数用来被后面的插入结点函数调用。
*/
int search_Node(BSTree pTree,int key,BSTree f,BSTree &p)
{
if(!pTree){
p = f;
return 0;
}else if(key == pTree->data){
p = pTree;
return 1;
}else if(key > pTree->data){
search_Node(pTree->rchild,key,pTree,p);
}else{
search_Node(pTree->lchild,key,pTree,p);
}

}

/*
往二叉排序树种插入结点
当在pTree所指向的二叉排序树中查找不到关键字为key的数据元素时,
将其插入该二叉排序树,并返回1,否则返回0。
树空时插入会改变根节点的值,因此要传入引用。

*/
int insertNode(BSTree &pTree,int key)
{
BSTree p;
if(!search_Node(pTree,key,NULL,p)){

BSTree pNew = (BSTree)malloc(sizeof(Node));  //产生新元素的结点
pNew->lchild = pNew->rchild = NULL;
pNew->data = key;

if(!p){
pTree = pNew;            //如何树空,直接将pNew置为根节点
}else{
if(key > p->data){
p->rchild = pNew;        //作为右孩子插入p的右边
}else{
p->lchild = pNew;        //作为左孩子插入p的左边
}
}
return 1;
}else
return 0;

}

//创建二叉排序树
BSTree create_BSTree(int *arr,int num)
{
BSTree pTree = NULL;
int i;
for(i=0;i<num;i++)
insertNode(pTree,arr[i]);
return pTree;

}

//递归中序遍历二叉树,得到元素从小到大的有序排列
void InorderTraverse(BSTree pTree)
{
if(pTree){
InorderTraverse(pTree->lchild);
printf("%d ",pTree->data);
InorderTraverse(pTree->rchild);
}
}

//修改左子树的方法删除结点
int delete_Node1(BSTree &p)
{
BSTree q,s;
if(!p->lchild){                  //左子树为空,只需重新接上右子树
q = p;
p = p->rchild;
free(q);
}else if(!p->rchild){        //右子树为空,只需重新接上左子树
q = p;
p = p->lchild;
free(q);
}else{                        //如果左右子树都不为空
//我们这里采取修改左子树的方法,也可以修改右子树,方法类似
q = p;
s = p->lchild;            //取待删节点的左节点
while(s->rchild){        //一直向右,最终s为待删节点的前驱节点。
//如果将各节点元素按从小到大顺序排列成一个序列,
//则某节点的前驱节点即为序列中该节点的前面一个节点
q = s;
s = s->rchild;
}
//用s来替换待删节点p
p->data = s->data;
//根据情况,将s的左子树重接到q上
if(p != q){
q->rchild = s->lchild;
}else{
q->lchild = s->lchild;
}
free(s);
}
return 1;
}

//修改右子树的方法删除结点
int delete_Node2(BSTree &p)
{
BSTree q,s;
if(!p->lchild){                //左子树为空,只需重新接上右子树
q = p;
p = p->rchild;
free(q);
}else if(!p->rchild){        //右子树为空,只需重新接上左子树
q = p;
p = p->lchild;
free(q);
}else{
q = p;
s = p->rchild;
while(s->lchild){
q = s;
s = s->lchild;
}
//用s来替换待删节点p
p->data = s->data;
//根据情况,将s的左子树重接到q上
if(p != q){
q->lchild = s->rchild;
}else{
q->rchild = s->rchild;
}
free(s);
}
return 1;
}

//删除结点
int delete_BSTree(BSTree &pTree,int key)
{
if(!pTree){            //不存在关键字为key的结点
return 0;
}else{
if(key == pTree->data){
//    return delete_Node1(pTree);
return delete_Node2(pTree);
}else if(key > pTree->data){
return delete_BSTree(pTree->rchild,key);
}else{
return delete_BSTree(pTree->lchild,key);
}
}
}

int main()
{
BSTree pTree;
int i,num,flag;
printf("请输入节点的个数:");
scanf("%d",&num);
//    printf("%d\n",num);

int *arr = (int *)malloc( num * sizeof(int));
for(i=0;i<num;i++)
scanf("%d",arr+i);

pTree = create_BSTree(arr,num);
printf("中序遍历该二叉排序树的结果:");
InorderTraverse(pTree);printf("\n");

printf("请输入要删除的结点:");
scanf("%d",&num);
flag = delete_BSTree(pTree,num);
if(flag){
printf("删除成功!\n");
}else{
printf("删除失败!\n");
}
printf("中序遍历该二叉排序树的结果:");
InorderTraverse(pTree);printf("\n");

return 0;
}


View Code

敲敲代码有益身心,嘎嘎

参考书籍:《大话数据结构》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: