C语言二叉排序树左旋,二叉排序树C语言实现二

在上一篇文章中(http://blog.csdn.net/xiaowang627/article/details/51332201),对二叉排序树的定义和查找、插入等操作进行了图文描述和C语言实现,本文将详解二叉搜索树的删除操作。

一、节点删除:如下图所示

eb286f36f44d173f03fa181caa3b2656.png

(1)删除叶节点(2、4、9、20):直接删除

(2)删除的节点只有一个孩子(左孩子或右孩子)(7、13):将这个节点的孩子提升替换该节点即可

如图所示,删除节点7:

6f485c92890745d9edd474d3ba48a396.png

(3)删除的节点有两个孩子节点(6、15、18)。需要保证删除该节点后仍然满足二叉排序树的性质,则必须要用该节点的中序后继替换该节点!再对该节点和替换节点的子树进行处理。

根据求节点中序后继的算法,一个节点的中序后继为该节点右子树上的最左节点,该后继节点必不存在左孩子,考虑两种情况,a、该后继节点为其右孩子(如节点6后继节点7为其右孩子);b、该后继节点不为其右孩子(如节点15,其后继节点17不为其右孩子)

情况a:直接将后继节点替换该节点,如下图删除节点6:

14a13d1fd79d4ae63d05b1517aaae743.png

情况b:先用后继节点右孩子替换该后继节点,再用后继节点替换源节点,如下图删除节点15

dd6bd962aeb59520102cbb3945ec423e.png

综上所述,将删除节点my_node的情形总结为以下几种:

1、my_node为叶节点

2、my_node仅有一个孩子

2.1、my_node有仅左孩子

2.2、my_node仅有右孩子

3、my_node既有左孩子又有右孩子

3.1、my_node后继为my_node->rchild(my_node->rchild无左孩子)

3.2、my_node后继不为my_node->rchild(my_node->rchild有左孩子)

代码:(此处代码以个人理解的通俗方式书写,可能比较冗长,有较大优化空间)

STnode *STree_Delete(STnode *tree, STnode *my_node)

{

STnode *parent=my_node->p;

STnode *suc_parent;

STnode *successor;

if(my_node->left==NULL && my_node->right==NULL)//叶节点

{

if(parent==NULL)//只有一个节点

return NULL;

if(my_node==parent->left)

parent->left=NULL;

else

parent->right=NULL;

}

else if(my_node->left && my_node->right==NULL)//仅有左孩子

{

if(parent==NULL)//删除根节点

{

return tree->left;

}

if(my_node==parent->left)

{

parent->left=my_node->left;

my_node->left->p=parent;

}

else

{

parent->right=my_node->left;

my_node->left->p=parent;

}

}

else if(my_node->left==NULL && my_node->right)//仅有右孩子

{

if(parent==NULL)//删除根节点

{

return tree->right;

}

if(my_node==parent->left)

{

parent->left=my_node->right;

my_node->right->p=parent;

}

else

{

parent->right=my_node->right;

my_node->right->p=parent;

}

}

else//有两个孩子

{

successor=STree_Successor(my_node);

if(successor == my_node->right)//my_node后继为my_node->rchild

{

if(my_node==parent->left)

{

parent->left=successor;

successor->p=parent;

successor->left=my_node->left;

}

else

{

parent->right=successor;

successor->p=parent;

successor->left=my_node->left;

}

}

else //my_node后继不为my_node->rchild

{

suc_parent=successor->p;

suc_parent->left=successor->right;

successor->right->p=suc_parent;

successor->right=my_node->right;

successor->left=my_node->left;

successor->p=my_node->p;

}

}

if(parent==NULL)//删除根节点

return successor;

else

return tree;

}

二、主函数,测试用例及其头文件等

#include

#include

typedef struct STnode

{

int key;//数据信息

struct STnode *left;//指向左孩子

struct STnode *right;//指向右孩子

struct STnode *p;//指向父节点

} STnode;

STnode* STree_Insert(STnode *tree, STnode *my_node);

void STree_Inorder(STnode *tree);

STnode *STree_Creat(STnode *tree, int arr[], int n);

STnode *STree_Find(STnode *tree, int my_key);

STnode *STree_Max(STnode *tree);

STnode *STree_Min(STnode *tree);

STnode *STree_Successor(STnode *my_node);

STnode *STree_Predecessor(STnode *my_node);

STnode *STree_Delete(STnode *tree, STnode *my_node);

int main(void)

{

int i;

int arr[]={15,6,20,3,7,17,21,4,13,19,9};

STnode *tree=NULL;

STnode *p;

tree=STree_Creat(tree, arr, 11);

STree_Inorder(tree);

printf("\n");

p=STree_Find(tree, 7);

printf("find the key: %d\n",p->key);

p=STree_Max(tree);

printf("the max key: %d\n", p->key);

p=STree_Min(tree);

printf("the min key: %d\n",p->key);

p=STree_Successor(STree_Find(tree, 7));

printf("the successor of 7 is %d\n",p->key);

p=STree_Predecessor(STree_Find(tree, 7));

printf("the predessor of 7 is %d\n",p->key);

//以下三组删除操作在同一颗树上连续进行;

p=STree_Delete(tree, STree_Find(tree, 4));

printf("delete the leaf node 4:");

STree_Inorder(p);

printf("\n");

p=STree_Delete(tree, STree_Find(tree, 20));

printf("delete the node 20 which only have left child:");

STree_Inorder(p);

printf("\n");

p=STree_Delete(tree, STree_Find(tree, 7));

printf("delete the node 7 which only have right child:");

STree_Inorder(p);

printf("\n");

//重置二叉排序树,实验删除节点6和15

tree=NULL;

tree=STree_Creat(tree, arr, 11);

p=STree_Delete(tree, STree_Find(tree, 6));

printf("delete the node 6 which have two children:");

STree_Inorder(p);

printf("\n");

p=STree_Delete(tree, STree_Find(tree, 15));

printf("delete the node 15 which have two children:");

STree_Inorder(p);

printf("\n");

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值