有序二叉树的创建,遍历,删除一个结点

删除结点详解

1. 首先判断根节点 `root` 是否为NULL,如果是,则直接返回NULL,表示树为空树。
2. 在树中搜索要删除的节点,使用指针 `p` 和 `pre` 进行遍历。其中,`p` 用来遍历整个树,`pre` 用来保存节点 `p` 的双亲节点。
3. 如果找到了要删除的节点 `p`,则执行以下操作:
   - 如果节点 `p` 是叶子节点(即没有左子树和右子树),则判断以下情况:
     - 如果节点 `p` 是根节点,则直接释放节点 `p` 并返回NULL,表示树为空树。
     - 如果节点 `p` 是左子树的叶子节点,则将其双亲节点 `pre` 的左子树指针置为NULL。
     - 如果节点 `p` 是右子树的叶子节点,则将其双亲节点 `pre` 的右子树指针置为NULL。
     - 最后释放节点 `p` 并将指针 `p` 置为NULL。
   - 如果节点 `p` 只有左子树或者只有右子树,则判断以下情况:
     - 如果节点 `p` 有左子树,则执行以下操作:
       - 如果节点 `p` 是根节点,则将树的根节点指针 `root` 指向节点 `p` 的左子树,并将节点 `p` 的左子树指针置为NULL。
       - 如果节点 `p` 的左子树中的最大值小于其双亲节点 `pre` 的值,则将节点 `p` 的左子树指针连接到双亲节点 `pre` 的左子树上,否则连接到右子树上。并将节点 `p` 的左子树指针置为NULL。
     - 如果节点 `p` 有右子树,则执行以下操作:
       - 如果节点 `p` 是根节点,则将树的根节点指针 `root` 指向节点 `p` 的右子树,并将节点 `p` 的右子树指针置为NULL。
       - 如果节点 `p` 的右子树中的最小值小于其双亲节点 `pre` 的值,则将节点 `p` 的右子树指针连接到双亲节点 `pre` 的左子树上,否则连接到右子树上。并将节点 `p` 的右子树指针置为NULL。
     - 最后释放节点 `p` 并将指针 `p` 置为NULL
   - 如果节点 `p` 既有左子树又有右子树,则执行以下操作:
     - 在节点 `p` 的左子树中寻找最大值或者在右子树中寻找最小值。为了方便起见,我们选择在左子树中寻找最大值。
     - 使用指针 `p2` 和 `pre2` 在左子树中寻找最大值。其中,`p2` 用来寻找左子树中的最大值,`pre2` 用来保存节点 `p2` 的双亲节点。
     - 找到最大值后,将最大值节点 `p2` 的数据与节点 `p` 的数据进行交换。
     - 如果最大值节点 `p2` 没有右子树,则直接释放节点 `p2` 并将指针置为NULL。同时将双亲节点 `pre2` 的左子树指针置为NULL。
     - 如果最大值节点 `p2` 有右子树,则将双亲节点 `pre2` 的右子树指针连接到节点 `p2` 的左子树上,并将最大值节点 p2 的右子树指针连接到节点 p 的右子树上。然后释放节点 p2 并将指针置为NULL。

#ifndef __BINARYTREE_H_
#define __BINARYTREE_H_

#include <stdio.h>
#include <stdlib.h>


typedef int Elemtype;

typedef struct BiTNode
{

	Elemtype data;
	struct BiTNode* lchild;
	struct BiTNode* rchild;
	
}Bitnode;

Bitnode* insert_node(Bitnode* root, Elemtype value);
Bitnode* creat_sort_tree();
void pre_orde(Bitnode* root);
void mid_orde(Bitnode* root);
void post_orde(Bitnode* root);
Bitnode* delete_a_node(Bitnode* root,Elemtype value);

#endif
#include "binarytree.h"


Bitnode* insert_node(Bitnode* root, Elemtype value)  //往树中插入元素,建立有序二叉树
{
	Bitnode* pnew = malloc(sizeof(Bitnode));
	
	pnew->data = value;
	pnew->lchild = NULL;
	pnew->rchild = NULL;

	Bitnode* p = root;
	
	if(root == NULL)
	{
		root = pnew;        
	}
	else
	{
		while(1)
		{
			if(p->data > value)      //插入元素比根结点小,插入到左子树中
			{
				if(p->lchild == NULL)        
				{
					p->lchild = pnew;
					break;
				}
				else
				{
					p = p->lchild;
				}
			}
			else if(p->data < value)    //插入元素比根结点大,插入到右子树中
			{
				if(p->rchild == NULL)
				{
					p->rchild = pnew;
					break;
				}
				else
				{
					p = p->rchild;
				}
			}
			else       //和根结点一样大,直接退出
			{
				break ;
			}
		}
	}
	return root;
}

Bitnode* creat_sort_tree()    	  //创建有序二叉树
{
	Elemtype value ;

	Bitnode* root = NULL;

	while(1)
	{
		scanf("%d",&value);
		if(value == 0)
		{
			break;
		}

		root = insert_node(root,value);
	}

	return root;
}


void pre_orde(Bitnode* root)   //先序递归遍历
{
	if(root == NULL)
	{
		return;
	}
	printf("%d ",root->data);
	pre_orde(root->lchild);
	pre_orde(root->rchild);
}

void mid_orde(Bitnode* root)  //中序递归遍历
{
	if(root == NULL)
	{
		return;
	}
	mid_orde(root->lchild);
	printf("%d ",root->data);
	mid_orde(root->rchild);
}

void post_orde(Bitnode* root)  //后序递归遍历
{
	if(root == NULL)
		{
			return;
		}
	post_orde(root->lchild);
	post_orde(root->rchild);
	printf("%d ",root->data);

}

Bitnode* search(Bitnode* root,Elemtype value)   //查找树的元素
{
	if(root == NULL || root->data == value)
	{
		return root;
	}

	return search(root->lchild,value);

	return search(root->rchild,value);
}

Bitnode* delete_a_node(Bitnode* root,Elemtype value)  //删除树中的结点
{
	if(root == NULL)
	{
		return NULL;
	}
	
		Bitnode* p = root;	//p来遍历整个树
		Bitnode* pre = NULL;	//用来保存结点p的双亲结点	

		while(p)         
		{
			if(p->data == value)
			{
				break;
			}
			else if(value < p->data )
			{
				pre = p;
				p = p->lchild;
			}
			else if(value>p->data )
			{
				pre = p;
				p = p->rchild;
			}
			
		}

		if(p == NULL)     //树种没有要删除的元素
		{
			return NULL;
		}
		//删除的结点为叶子结点
		else if(p->lchild == NULL && p->rchild == NULL)
		{
			if(p == root)    //只有一个根节点
			{
				free(p);
				return NULL;
			}
			
			else if(pre->lchild == p)  //删除的为左子树的叶子结点
			{
				pre->lchild = NULL;
			}			
			else if(pre->rchild == p)	//删除的为右子树的叶子结点
			{
				pre->rchild = NULL;
			}
			free(p);
			p = NULL;	
		}
		//删除的结点只有左子树或者为右子树
		else if(p->lchild == NULL || p->rchild == NULL)
		{
			if(p->lchild)   //左子树存在
			{
				if(p == root)	
				{
					root = p->lchild;
					p->lchild = NULL;
				}
				else if(p->lchild->data < pre->data)  //如果p左子树的值比p的双亲结点小插入到左子树,否则右子树
				{
					pre->lchild = p->lchild;
					p->lchild = NULL;
				}
				else
				{
					pre->rchild = p->lchild;
					p->lchild = NULL;
				}
			}
			else if(p->rchild)
			{
				if(p == root)
				{
					root = p->rchild;
					p->rchild = NULL;
				}
				else if(p->rchild->data < pre->data) //如果p右子树的值比p的双亲结点小插入到左子树,否则右子树
				{
					pre->lchild = p->rchild;
					p->rchild = NULL;
				}
				else
				{
					pre->rchild = p->rchild;
					p->rchild = NULL;
				}
			}
		
			free(p);
			p = NULL;
		}
		else 
		{
			//a. 从待删除的结点的左子树中查找一个最大值或者从右子树中查找一个最小值
		    //搜索p的左子树中的最大值
			Bitnode* p2 = p->lchild;   //用来寻找左子树中的最大值
			Bitnode* pre2 = NULL;		//用来保存p2的双亲

			while(p2->rchild)
			{
				pre2 = p2;
				p2 = p2->rchild;
			}

			//b. 将查找到的结点(p2)与需要删除的结点(p)进行数据的交换
			//p2没有右子树,即p的左子树中最大值所在的结点就是p2
			if(p2 == p->lchild)
			{
				Elemtype temp = p->data;
				p->data = p2->data;
				p2->data = temp;
				
				pre2->lchild = p->lchild;
				p->lchild = NULL;
				
				free(p2);
				p2 = NULL;	
			}
			else
			{
				Elemtype temp = p->data;
				p->data = p2->data;
				p2->data = temp;

				pre2->rchild = p2->lchild;
				p2->lchild = NULL;

				free(p2);
				p2 = NULL;
			}
		}
	return root;
}
#include "binarytree.h"

int main()
{
	Bitnode* root = creat_sort_tree();
	root = delete_a_node(root,8);
	//Linkedqueue* queue= init_linkedqueue();
	pre_orde(root);
	printf("\n");
	mid_orde(root);
	printf("\n");
	post_orde(root);
	printf("\n");
	//level(root,queue);
}

点个赞吧,谢谢你

  • 22
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值