二叉排序树及其相关操作(C语言)

本文详细介绍了如何在C语言中实现二叉排序树,包括搜索、插入、删除操作,以及递归和非递归的中序遍历方法,提供了一个完整的示例代码并展示了删除单分支结点的处理过程。
摘要由CSDN通过智能技术生成

写这篇文章前,我把我之前写的二叉排序树的代码改了许多回,终于改好了。

话不多说,上代码。

首先是一些前期准备如下:

​

#include"stdio.h"
#include"stdlib.h"
#define StackInitSize 100
#define Maxsize 100
typedef void Status;
typedef int TElemType;
typedef struct BiTNode {
	TElemType data;
	struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree,BSTNode;
typedef BiTree SElemType;

typedef struct Stack{
	SElemType *top;
	SElemType *base;
	int size;
}Stack;

bool EmptyStack(Stack S){
	if(S.base==S.top)
	return true;
	return false;
}
Status Pop(Stack &S,SElemType &e){
	if (EmptyStack(S))return; 
	e=*S.top;
	S.top--;
	
}
Status Push(Stack &S,SElemType e){
	if(S.top-S.base>=99)return;
	S.top++;
	*(S.top)=e;
}
Status InitStack(Stack &S){
	S.base=S.top=(SElemType *)malloc(StackInitSize*sizeof(SElemType));
	if(!S.base)
	return;
	S.size=StackInitSize;
}
void InitBiTree(BiTree &BT){
	BT=(BiTNode*)malloc(sizeof(BiTNode));
	BT=NULL;
}

​

接着开始进入正题,以下是相关函数:

1.二叉排序树的搜索

 

​
BiTree Search_BST(BiTree BT,int key){//递归搜索二叉排序树 
	if(BT==NULL)return NULL;
	if(key<BT->data) return Search_BST(BT->lchild,key);
	else if(key>BT->data) return Search_BST(BT->rchild,key);
	else return BT;
}
BiTree Search_BST2(BiTree BT,int key,BiTree *parent){//非递归搜索二叉排序树 
	BiTNode *p=BT;
	while(p!=NULL){
		if(key<p->data) {*parent=p;p=p->lchild;}
		else if(key>p->data) {*parent=p;p=p->rchild;}
		else return p;
	}
	return NULL;
}

​

2.二叉排序树的插入

void Insert_BST(BiTree &BT,int key){

	BiTree p=(BiTree)malloc(sizeof(BiTree)); //初始化插入节点
	if(p==NULL) return;
	p->data=key;
	p->lchild=p->rchild=NULL;
	if(BT==NULL){//空树时,直接作为根节点
		BT=p;
		return;
	}
    //是否存在,已存在则返回,不插入
    if (Search_BST(BT,key) != NULL) return; 
	BiTree tnode=BT,parent=NULL;    //进行插入,首先找到要插入的位置的父节点
	while(tnode){
		parent=tnode;
		if(key<tnode->data)tnode=tnode->lchild;//到最后tnode会为NULL,parent会保存着父节点 
		else tnode=tnode->rchild;
	}
	if(key<parent->data) parent->lchild=p;
	else parent->rchild=p;
		
}

3.二叉排序树的构造

void CreateBST(BiTree &BT, int a[], int n)
{
    int i;
    for (i = 0; i < n; i++)
    {
        Insert_BST(BT, a[i]);
    }
}

4.二叉排序树的删除的辅助函数

void Delete_BT(BiTree &BT){
	BiTree p=BT;
	if(p->lchild&&!p->rchild){
		BT=p->lchild;
		free(p);
	}
	else if(!p->lchild&&p->rchild){
		BT=p->rchild;
		free(p);
	}
}
BiTree SearchMin(BiTree BT)//递归 
{
    if (BT == NULL)
        return NULL;
    if (BT->lchild == NULL)
        return BT;
    else  //一直往左孩子找,直到没有左孩子的结点  
        return SearchMin(BT->lchild);
}
BiTree SearchMax(BiTree BT)//非递归 
{
    if (BT == NULL)
        return NULL;
	BiTree p=BT;
	while(p->rchild){
		p=p->rchild;
	}
	return p;
}

注意:这里SearchMax其实也可以写成递归的形式,对比SearchMin就会了。

5.二叉排序树的删除

(1)以前驱替代

p的前驱:p的左子树中key最大的结点

void DeleteBSTNode_pre(BiTree &BT, int key)//以前驱替代 
{
	BiTree pre,parent;
	BiTree p =Search_BST2(BT,key,&parent);
	if(p==BT){
		Delete_BT(BT);
		return;
	} 
	if(!p->lchild&&!p->rchild) {//lchild,rchild都不存在
		if(p->data<parent->data) parent->lchild=NULL;
		else parent->rchild=NULL;
	}
	else if(!p->lchild&&p->rchild) {//rchild存在	
		if(p->data<parent->data) parent->lchild=p->rchild;//p的data小于parent 的,故后写lchild
		else parent->rchild=p->rchild;//p的data大于parent 的,故后写rchild 
	} 
	else if(p->lchild&&!p->rchild) {//lchild存在 
		if(p->data<parent->data) parent->lchild=p->lchild;
		else parent->rchild=p->lchild;
	}
	else{//lchild,rchild都存在
		pre=SearchMax(p->lchild);
		if(pre==p->lchild) {//说明pre结点没有右孩子 
			p->data=pre->data;
			p->lchild=pre->lchild;
		}
		else{
			p->data=pre->data;
			DeleteBSTNode_pre(p->lchild,pre->data);
		}
	}
}

(2)以后继替代

p的后继:p的右子树中key最小的结点

void DeleteBSTNode_pos(BiTree &BT, int key)//以后继替代 
{
	BiTree pos,parent;
	BiTree p =Search_BST2(BT,key,&parent);
	if(p==BT){
		Delete_BT(BT);
		return;
	} 
	if(!p->lchild&&!p->rchild) {//lchild,rchild都不存在 
		if(p->data<parent->data) parent->lchild=NULL;
		else parent->rchild=NULL;
	}
	else if(!p->lchild&&p->rchild) {//rchild存在	
		if(p->data<parent->data) parent->lchild=p->rchild;//p的data小于parent 的,故后写lchild 
		else parent->rchild=p->rchild;//p的data大于parent 的,故后写rchild 
	} 
	else if(p->lchild&&!p->rchild) {//lchild存在 
		if(p->data<parent->data) parent->lchild=p->lchild;
		else parent->rchild=p->lchild;
	}
	else{//lchild,rchild都存在
		pos=SearchMin(p->rchild);
		if(pos==p->rchild) {//说明pos结点没有左孩子 
			p->data=pos->data;
			p->rchild=pos->rchild;
		}
		else{
			p->data=pos->data;
			DeleteBSTNode_pos(p->rchild,pos->data);
		}
	}
}

6.中序遍历

(1)递归版

void InOrder(BiTree BT){// 中序递归遍历 
	if(BT){//BT不为空时执行以下语句 
		InOrder(BT->lchild);
		printf("%d ",BT->data);
		InOrder(BT->rchild);
	}
}

(2)非递归版

//中序非递归遍历二叉树
Status NRInOrder(BiTree BT,Stack &S)
{
	BiTNode *p;
	p=BT;
	while(p|| !EmptyStack(S)){
		if(p){
			Push(S,p);
			p=p->lchild;
		}
		else{
			Pop(S,p);
			printf("%d ",p->data);
			p=p->rchild;
		}
	}

}

7.测试数据

8.用来理解删除单分支结点时的情况的

9.完整代码


#include"stdio.h"
#include"stdlib.h"
#define StackInitSize 100
#define Maxsize 100
typedef void Status;
typedef int TElemType;
typedef struct BiTNode {
	TElemType data;
	struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree,BSTNode;
typedef BiTree SElemType;

typedef struct Stack{
	SElemType *top;
	SElemType *base;
	int size;
}Stack;

bool EmptyStack(Stack S){
	if(S.base==S.top)
	return true;
	return false;
}
Status Pop(Stack &S,SElemType &e){
	if (EmptyStack(S))return; 
	e=*S.top;
	S.top--;
	
}
Status Push(Stack &S,SElemType e){
	if(S.top-S.base>=99)return;
	S.top++;
	*(S.top)=e;
}
Status InitStack(Stack &S){
	S.base=S.top=(SElemType *)malloc(StackInitSize*sizeof(SElemType));
	if(!S.base)
	return;
	S.size=StackInitSize;
}
void InitBiTree(BiTree &BT){
	BT=(BiTNode*)malloc(sizeof(BiTNode));
	BT=NULL;
}
BiTree Search_BST(BiTree BT,int key){//递归搜索二叉排序树 
	if(BT==NULL)return NULL;
	if(key<BT->data) return Search_BST(BT->lchild,key);
	else if(key>BT->data) return Search_BST(BT->rchild,key);
	else return BT;
}
BiTree Search_BST2(BiTree BT,int key,BiTree *parent){//非递归搜索二叉排序树 
	BiTNode *p=BT;
	while(p!=NULL){
		if(key<p->data) {*parent=p;p=p->lchild;}
		else if(key>p->data) {*parent=p;p=p->rchild;}
		else return p;
	}
	return NULL;
}
void Insert_BST(BiTree &BT,int key){

	BiTree p=(BiTree)malloc(sizeof(BiTree)); //初始化插入节点
	if(p==NULL) return;
	p->data=key;
	p->lchild=p->rchild=NULL;
	if(BT==NULL){//空树时,直接作为根节点
		BT=p;
		return;
	}
    //是否存在,已存在则返回,不插入
    if (Search_BST(BT,key) != NULL) return; 
	BiTree tnode=BT,parent=NULL;    //进行插入,首先找到要插入的位置的父节点
	while(tnode){
		parent=tnode;
		if(key<tnode->data)tnode=tnode->lchild;//到最后tnode会为NULL,parent会保存着父节点 
		else tnode=tnode->rchild;
	}
	if(key<parent->data) parent->lchild=p;
	else parent->rchild=p;
		
}
void Delete_BT(BiTree &BT){
	BiTree p=BT;
	if(p->lchild&&!p->rchild){
		BT=p->lchild;
		free(p);
	}
	else if(!p->lchild&&p->rchild){
		BT=p->rchild;
		free(p);
	}
}
BiTree SearchMin(BiTree BT)//递归 
{
    if (BT == NULL)
        return NULL;
    if (BT->lchild == NULL)
        return BT;
    else  //一直往左孩子找,直到没有左孩子的结点  
        return SearchMin(BT->lchild);
}
BiTree SearchMax(BiTree BT)//非递归 
{
    if (BT == NULL)
        return NULL;
	BiTree p=BT;
	while(p->rchild){
		p=p->rchild;
	}
	return p;
}
void CreateBST(BiTree &BT, int a[], int n)
{
    int i;
    for (i = 0; i < n; i++)
    {
        Insert_BST(BT, a[i]);
    }
}
void DeleteBSTNode_pre(BiTree &BT, int key)//以前驱替代 
{
	BiTree pre,parent;
	BiTree p =Search_BST2(BT,key,&parent);
	if(p==BT){
		Delete_BT(BT);
		return;
	} 
	if(!p->lchild&&!p->rchild) {//lchild,rchild都不存在
		if(p->data<parent->data) parent->lchild=NULL;
		else parent->rchild=NULL;
	}
	else if(!p->lchild&&p->rchild) {//rchild存在	
		if(p->data<parent->data) parent->lchild=p->rchild;//p的data小于parent 的,故后写lchild
		else parent->rchild=p->rchild;//p的data大于parent 的,故后写rchild 
	} 
	else if(p->lchild&&!p->rchild) {//lchild存在 
		if(p->data<parent->data) parent->lchild=p->lchild;
		else parent->rchild=p->lchild;
	}
	else{//lchild,rchild都存在
		pre=SearchMax(p->lchild);
		if(pre==p->lchild) {//说明pre结点没有右孩子 
			p->data=pre->data;
			p->lchild=pre->lchild;
		}
		else{
			p->data=pre->data;
			DeleteBSTNode_pre(p->lchild,pre->data);
		}
	}
}
void DeleteBSTNode_pos(BiTree &BT, int key)//以后继替代 
{
	BiTree pos,parent;
	BiTree p =Search_BST2(BT,key,&parent);
	if(p==BT){
		Delete_BT(BT);
		return;
	} 
	if(!p->lchild&&!p->rchild) {//lchild,rchild都不存在 
		if(p->data<parent->data) parent->lchild=NULL;
		else parent->rchild=NULL;
	}
	else if(!p->lchild&&p->rchild) {//rchild存在	
		if(p->data<parent->data) parent->lchild=p->rchild;//p的data小于parent 的,故后写lchild 
		else parent->rchild=p->rchild;//p的data大于parent 的,故后写rchild 
	} 
	else if(p->lchild&&!p->rchild) {//lchild存在 
		if(p->data<parent->data) parent->lchild=p->lchild;
		else parent->rchild=p->lchild;
	}
	else{//lchild,rchild都存在
		pos=SearchMin(p->rchild);
		if(pos==p->rchild) {//说明pos结点没有左孩子 
			p->data=pos->data;
			p->rchild=pos->rchild;
		}
		else{
			p->data=pos->data;
			DeleteBSTNode_pos(p->rchild,pos->data);
		}
	}
}
void InOrder(BiTree BT){// 中序递归遍历 
	if(BT){//BT不为空时执行以下语句 
		InOrder(BT->lchild);
		printf("%d ",BT->data);
		InOrder(BT->rchild);
	}
}
//!EmptyQueue(Q)
//!EmptyStack(S)

//中序非递归遍历二叉树
Status NRInOrder(BiTree BT,Stack &S)
{
	BiTNode *p;
	p=BT;
	while(p|| !EmptyStack(S)){
		if(p){
			Push(S,p);
			p=p->lchild;
		}
		else{
			Pop(S,p);
			printf("%d ",p->data);
			p=p->rchild;
		}
	}

}

int main(){
	BiTree BT;
	Stack S;
	InitStack(S);
	InitBiTree(BT);
	int arr[] = { 10,6,11,4,7,13,3,5,8,12};
	CreateBST(BT,arr,10);
	printf("\n中序遍历的结果为:\n");//中序遍历的结果应该为递增顺序
	InOrder(BT);
	DeleteBSTNode_pre(BT,4);
	printf("\n中序遍历的结果为:\n");
	InOrder(BT);
	return 0;
} 
//{10,6,12,4,8,11,14,5,7,13}  二叉排序树1 
//{10,6,11,4,7,13,3,5,8,12}  二叉排序树2 
//{10,8,6,4,2} 删除根节点10 试试看


总体代码就是这样了,我进行过多次测试,应该没有什么大问题了。

如果有什么写的不好的地方请指正,谢谢大家!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值