c语言递归实现二叉排序树的插入与删除

目录

什么是二叉排序树?

 结构体定义

二叉排序树的插入实现

二叉排序树的删除实现

完整代码:

test.c文件

bst.h文件

bst.c文件

lstack.h文件

lstack.c文件


前言

本文编者主要尽最大能力分享二叉树的插入与删除实现的思路,编者水平有限,如有不妥之处请网友们多多指教。与大家相互学习进步。

什么是二叉排序树?

二叉排序树(Binary Sort Tree,BST)又称为二叉搜索树。图1是典型的二叉排序树,二叉排序树可能是一颗空树。或者具有以下性质:

图1 二叉排序树

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。

图2 删除有左右孩子都有的节点

 下面使用递归实现二叉排序树的节点删除,代码如下:

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;
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
二叉排序树是一种二叉树,它满足以下条件: 1. 左子树中所有结点的值都小于根结点的值; 2. 右子树中所有结点的值都大于根结点的值; 3. 左右子树都是二叉排序树。 基于这个定义,我们可以实现二叉排序树的结点查找和插入操作,具体步骤如下: 1. 结点查找:从根结点开始,如果要查找的值比当前结点的值小,则在左子树中继续查找;如果要查找的值比当前结点的值大,则在右子树中继续查找;如果要查找的值等于当前结点的值,则查找成功;如果查找到叶子结点仍未找到,则查找失败。 2. 结点插入:从根结点开始,如果要插入的值比当前结点的值小,则在左子树中继续插入;如果要插入的值比当前结点的值大,则在右子树中继续插入;如果要插入的值等于当前结点的值,则插入失败;如果插入到叶子结点,则将新结点插入到该位置,插入成功。 具体实现时,我们可以使用非递归的方式实现结点的查找和插入操作。具体代码如下: ```python class TreeNode: def __init__(self, val): self.val = val self.left = None self.right = None class BST: def __init__(self): self.root = None # 结点查找 def search(self, val): curr = self.root while curr: if val == curr.val: return curr elif val < curr.val: curr = curr.left else: curr = curr.right return None # 结点插入 def insert(self, val): if not self.root: self.root = TreeNode(val) return True curr = self.root while curr: if val == curr.val: return False elif val < curr.val: if not curr.left: curr.left = TreeNode(val) return True else: curr = curr.left else: if not curr.right: curr.right = TreeNode(val) return True else: curr = curr.right return False ``` 以上代码实现了非递归二叉排序树结点查找和插入操作,可以在 O(log n) 的时间复杂度内完成。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值