目录
前言
本文编者主要尽最大能力分享二叉树的插入与删除实现的思路,编者水平有限,如有不妥之处请网友们多多指教。与大家相互学习进步。
什么是二叉排序树?
二叉排序树(Binary Sort Tree,BST)又称为二叉搜索树。图1是典型的二叉排序树,二叉排序树可能是一颗空树。或者具有以下性质:
![](https://i-blog.csdnimg.cn/blog_migrate/c3252bff7e8713a9661abf88059cd113.jpeg)
1.如果左子树不为空,则左子树上任意一个节点值均小于根节点值。
2.如果右子树不为空,则右子树上任意一个节点值均大于根节点值。
3.左右子树都是二叉排序树。
4.树中没有相同的节点。
如果采用中序遍历遍历图1所示二叉树结果为:1 3 4 6 7 8 10 13 14,由此可见二叉排序树的中序遍历得到的结果是该树的递增序列,这也是二叉排序树的一个特性。
结构体定义
typedef int data_t;
typedef struct BstNode{
data_t data;
struct BstNode *lchild,*rchild;//左右孩子
}*Bst;
二叉排序树的插入实现
二叉排序树在插入时,要保证插入节点后,该二叉树依然有二叉排序树的特性。
如果二叉排序树为空树,则把待插入的节点作为根节点。
如果不是空树,就和根节点进行比较,如果两者相等,无需插入,如果小于根节点,则把带插入元素插入到左子树中,如果大于根节点,则把待插入元素插入到右子树中。具体实现代码如下所示:
int Bst_Insert(Bst *root,data_t key)
{
if(root == NULL) return -1;//root是空指针
struct BstNode *p = *root;
struct BstNode *parent = NULL;
struct BstNode *temp = NULL;
while(p != NULL)
{
parent = p;
if(key > p->data){
p = p->rchild;
}else if(key < p->data){
p = p->lchild;
}else if(key == p->data){
return -2;//待插入的节点和树中的节点相同,不进行插入。
}
}
temp =(struct BstNode*)malloc(sizeof(struct BstNode));
if(temp == NULL) return -3;//申请内存失败了
temp->lchild = temp->rchild = NULL;
temp->data = key;
if(parent != NULL){
if(key > parent->data)
{
parent->rchild = temp;
}else if(key < parent->data){
parent->lchild = temp;
}
}else{
//parent = NULL,说明是空树直接把待插入节点作为根节点
*root = temp;
}
return 0;//成功
}
二叉排序树的删除实现
二叉排序树删除的稍微情况复杂点,大致分为三种情况:
删除的元素是叶子节点:先直接删除,然后把父节点的指针置为NULL。
删除的元素只有左孩子或者右孩子:先让左/右孩子代替其位置,然后删除,该节点。
删除的元素左孩子和右孩子都有:找到该元素左子树中最大的元素的节点,然后把这个元素的值赋值到覆盖要删除的元素的节点,最后去删除其左子树的最大的元素的节点。
比如图1所示的二叉排序树,它的根节点左右子树都有,根节点的值原来是8,我们要先找到左子树最大元素,显然左子树的最大元素是7,先覆盖待删除节点的值,然后删除左子树的最大元素值。这一就达到了删除根节点8的目的,删除过程见图2。
![](https://i-blog.csdnimg.cn/blog_migrate/3d831de7bafab368499316078b85c20f.jpeg)
下面使用递归实现二叉排序树的节点删除,代码如下:
int Bst_Delete(Bst *root,data_t key)
{
if(root == NULL) return -1;//root是空指针
if(*root == NULL) return -2;//空树
if(key > (*root)->data)
{
Bst_Delete(&((*root)->rchild),key);
}else if(key < (*root)-> data){
Bst_Delete(&((*root)->lchild),key);
}else{
//找到要删除的节点
if((*root)->lchild == NULL && (*root)->rchild == NULL)
{
//叶节点
free(*root);
*root = NULL;
}else if((*root)->lchild == NULL){
//只有右孩子
struct BstNode* temp = (*root)->rchild;
free(*root);
*root = temp;//右孩子代替其位置
}else if((*root)->rchild == NULL){
//只有左孩子
struct BstNode* temp = (*root)->lchild;
free(*root);
*root = temp;//左孩子代替其位置
}else{
//找左子树的最大节点
struct BstNode* temp = (*root)->lchild;
while(temp->rchild != NULL)
{
temp=temp->rchild;
}
(*root)->data = temp->data;//左子树最大节点的值覆盖待删除节点值
Bst_Delete(&((*root)->lchild),temp->data);//删除左子树最大节点
}
}
return 0;//成功
}
完整代码:
本程序中序遍历采用的是非递归实现,递归法实现中序遍历不在本文讨论范围。
文件说明:
test.c 测试
bts.h 二叉搜索树头文件
bst.c 二叉搜索树相关函数实现
lstack.h 链式栈头文件
lstack.c 链式栈相关函数实现
test.c文件
#include<stdio.h>
#include"bst.h"
int main()
{
Bst tree = NULL;
data_t dat[9] ={8,3,10,1,6,14,13,4,7};
for(int i = 0; i < sizeof(dat)/sizeof(int); i++)
{
Bst_Insert(&tree,dat[i]);
}
Bst_Inorder(tree);
printf("\n");
Bst_Delete(&tree,8);
Bst_Inorder(tree);
printf("\n");
Bst_Delete(&tree,1);
Bst_Inorder(tree);
printf("\n");
if(Bst_free(tree) == 0)
{
printf("free succeed.\n");
}else{
printf("free failed.\n");
}
return 0;
}
运行结果:
1 3 4 6 7 8 10 13 14
1 3 4 6 7 10 13 14
3 4 6 7 10 13 14
free succeed.
bst.h文件
#ifndef _BST_H_
#define _BST_H_
typedef int data_t;
typedef struct BstNode{
data_t data;
struct BstNode *lchild,*rchild;
}*Bst;
Bst Bst_Create(data_t key);
struct BstNode* Bst_Search(Bst root,data_t key);
int Bst_Insert(Bst *root,data_t key);
int Bst_Delete(Bst *root,data_t key);
int Bst_Inorder(Bst root);
int Bst_free(Bst root);
#endif
bst.c文件
#include"bst.h"
#include<stdio.h>
#include<stdlib.h>
#include"lstack.h"
Bst Bst_Create(data_t key)//创建一个只有根节点的二叉树
{
Bst t = NULL;
t = (Bst)malloc(sizeof(struct BstNode));
if(t == NULL)return NULL;
t->lchild = t->rchild = NULL;
t->data = key;
return t;
}
struct BstNode* Bst_Search(Bst root,data_t key)//搜索
{
if(root == NULL) return NULL;
struct BstNode* p = root;
while(p != NULL)
{
if(key > p->data)
{
p = p->rchild;
}else if(key < p->data)
{
p = p->lchild;
}else if(key == p->data){
break;
}
}
return p;
}
int Bst_Insert(Bst *root,data_t key)//插入
{
if(root == NULL) return -1;
struct BstNode *p = *root;
struct BstNode *parent = NULL;
struct BstNode *temp = NULL;
while(p != NULL)
{
parent = p;
if(key > p->data){
p = p->rchild;
}else if(key < p->data){
p = p->lchild;
}else if(key == p->data){
return -2;
}
}
temp =(struct BstNode*)malloc(sizeof(struct BstNode));
if(temp == NULL) return -3;
temp->lchild = temp->rchild = NULL;
temp->data = key;
if(parent != NULL){
if(key > parent->data)
{
parent->rchild = temp;
}else if(key < parent->data){
parent->lchild = temp;
}
}else{
*root = temp;
}
return 0;
}
int Bst_Delete(Bst *root,data_t key)//删除
{
if(root == NULL) return -1;
if(*root == NULL) return -2;
if(key > (*root)->data)
{
Bst_Delete(&((*root)->rchild),key);
}else if(key < (*root)-> data){
Bst_Delete(&((*root)->lchild),key);
}else{
if((*root)->lchild == NULL && (*root)->rchild == NULL)
{
free(*root);
*root = NULL;
}else if((*root)->lchild == NULL){
struct BstNode* temp = (*root)->rchild;
free(*root);
*root = temp;
}else if((*root)->rchild == NULL){
struct BstNode* temp = (*root)->lchild;
free(*root);
*root = temp;
}else{
struct BstNode* temp = (*root)->lchild;
while(temp->rchild != NULL)
{
temp=temp->rchild;
}
(*root)->data = temp->data;
Bst_Delete(&((*root)->lchild),temp->data);
}
}
return 0;
}
int Bst_Inorder(Bst root)//非递归实现中序遍历
{
if(root == NULL) return -1;
lstack ls = lstack_create();
if(ls == NULL) return -2;
lstack_push(ls,root);
while(!(lstack_isempty(ls)))
{
if(lstack_gettop(ls)->lchild != NULL)
{
lstack_push(ls,lstack_gettop(ls)->lchild);
}else{
while(!(lstack_isempty(ls)))
{
struct BstNode *p = lstack_pop(ls);
printf("%d ", p->data);
if(p->rchild != NULL)
{
lstack_push(ls,p->rchild);
break;
}
}
}
}
free(ls);
return 0;
}
int Bst_free(Bst root)//销毁二叉树
{
if(root == NULL) return -1;
Bst_free(root->lchild);
Bst_free(root->rchild);
free(root);
return 0;
}
lstack.h文件
#ifndef _LSTACK_H_
#define _LSTACK_H_
#include"bst.h"
typedef struct stack_node
{
struct BstNode *data;
struct stack_node *next;
}*lstack;
lstack lstack_create();
int lstack_isempty(lstack ls);
struct BstNode* lstack_pop(lstack ls);
int lstack_push(lstack ls, struct BstNode* dat);
struct BstNode* lstack_gettop(lstack ls);
int lstack_free(lstack ls);
#endif
lstack.c文件
#include<stdio.h>
#include<stdlib.h>
#include"lstack.h"
lstack lstack_create()//创建一个空栈
{
lstack ls = NULL;
ls = (lstack)malloc(sizeof(struct stack_node));
if(ls == NULL) return NULL;
ls->data = NULL;
ls->next = NULL;
return ls;
}
int lstack_isempty(lstack ls)//判断栈是否为空
{
if(ls == NULL) return -1;
return (ls->next == NULL);
}
struct BstNode* lstack_pop(lstack ls)//出栈
{
if(ls == NULL) return NULL;
if(ls->next == NULL) return NULL;
struct BstNode *temp = ls->next->data;
struct stack_node *sn = ls->next;
ls->next = ls->next->next;
free(sn);
return temp;
}
int lstack_push(lstack ls, struct BstNode* dat)//入栈
{
if(ls == NULL) return -1;
if(dat == NULL) return -2;
struct stack_node *p = (struct stack_node*)malloc(sizeof(struct stack_node));
if(p == NULL) return -3;
p->data = dat;
p->next = ls->next;
ls->next = p;
return 0;
}
struct BstNode* lstack_gettop(lstack ls)//获取栈顶元素的指针
{
if(ls == NULL) return NULL;
if(ls->next == NULL) return NULL;
return ls->next->data;
}
int lstack_free(lstack ls)//销毁一个栈
{
if(ls == NULL) return -1;
struct stack_node *p = ls;
while(p != NULL)
{
struct stack_node *t = p->next;
free(p);
p = t;
}
return 0;
}