二叉搜索树= = //

特点= =//

没有重复的元素

每个节点左侧的数都小于该节点,该节点右侧的数都大于该节点

每棵子树都是一颗二叉搜索树

好处= =//

使用时消耗的时间取决于树的高度= =//

但是如果树退化成单枝树= =//耗子尾汁哈

操作= =//

中序遍历

中序遍历二叉树,从小到大打印
若想从大到小输出,只要把两次递归的顺序调换即可= =或者你也可以自己用个mode控制

//中序遍历二叉树,从小到大打印
//若想从大到小输出,只要把两次递归的顺序调换即可= =或者你也可以自己用个mode控制
void InOder(BSTree ptr)
{
	if (ptr != nullptr)
	{
		InOder(ptr->lchild);
		cout << ptr->key << " ";
		InOder(ptr->rchild);
	}
}

插入节点

插入时要注意,重复的数据在插入时会自动排除= =//

同时如果想的话,你也可以自己记录一下节点个数

//购买一个节点供自己使用(奢侈脸)
BSTree BuyNode()		
{
	BSTree t = (BstNode*)malloc(sizeof(BstNode));
	if (nullptr == t)		exit(1);
	memset(t, 0, sizeof(BstNode));				//初始化节点
	return t;
}
//给大树造根
BSTree MakeRoot(KeyType kx)
{
	BSTree s = BuyNode();
	s->key = kx;
	return s;
}
//插入节点
BSTree Insert(BSTree ptr, KeyType kx)
{
	if (ptr == nullptr)				//无根就造一个根出来
	{
		ptr = MakeRoot(kx);
		return ptr;
	}
	BSTree par = nullptr;			//记录上一个节点(父节点)
	BSTree p = ptr;					
	while (p != nullptr && p->key != kx)		//寻找位置并排查数据
	{
		par = p;
		p = kx < p->key ? p->lchild : p->rchild;
	}
	if (p != nullptr && p->key == kx)		return ptr;		//如果发现数据有重复
	p = BuyNode();					//奢侈一下
	p->key = kx;					
	p->parent = par;				//连接节点
	if (p->key < par->key)		par->lchild = p;			//反向连接
	else  par->rchild = p;
	return ptr;
}

寻找某树的最大最小值

最小值在左下角,最大值在右下角

//寻找树中的最小值
BSTree FindMin(BSTree ptr)
{
	BSTree t = ptr;
	//最小值一定在左下角
	while (t != nullptr && t->lchild != nullptr)		
		t = t->lchild;
	return t;

}
//寻找树中的最大值
BSTree FindMax(BSTree ptr)
{
	BSTree t = ptr;
	//最大值一定在右下角
	while (t != nullptr && t->rchild != nullptr)
		t = t->rchild;
	return t;
}

寻找前驱和后继

就是刚好比他大又或刚好比他小的了。。

刚好比他大:将树中数据排序后,比他大且离他最近

BSTree Prev(BSTree pt)
{
	BSTree ptr = pt;
	if (ptr == nullptr)	return nullptr;
	//如果有左子树就在左子树里找
	if (ptr->lchild != nullptr)		return FindMax(ptr->lchild);	//比它小的数里找最大	
	else
	{
		//没有左子树就顺藤摸瓜向上找
		BSTree par = ptr->parent;
		while (par != nullptr && par->rchild != ptr)
		{
			ptr = par;
			par = ptr->parent;
		}
		return par;
	}
}
//寻找当前节点的后继节点			
//就是数据比它大且离他最近	
BSTree Next(BSTree pt)
{
	BSTree ptr = pt;
	if (ptr == nullptr)		return nullptr;
	if (ptr->rchild != nullptr)		return FindMin(ptr->rchild);	//比它大的数里找最小
	else
	{
		BSTree par = ptr->parent;
		while (par != nullptr && par->lchild != ptr)
		{
			ptr = par;
			par = ptr->parent;
		}
		return par;
	}
}

删除节点

因为该类二叉树没有重复的元素

所以只要指定要删除的数据,即可删除其对应的节点

(先找到该数据的位置,然后进行删除= =//)

如果树中没有这个数据,直接开溜= =//

重要的是,

我们要删除的节点会分为三种类型:无孩子(叶子),有一个孩子,有两个孩子

无孩子的节点,我们找到其位置直接删除即可

有一个孩子的节点,直接帮助其儿子谋权篡位,顶替他的父亲即可

至于有两个孩子的节点(幸福美满)= =//

我们就要找一个数据刚好比它小,或者刚好比它大的节点,我们称之为该节点的前驱和后继

然后使用其前驱或后继的数据代替父节点的数据,然后删除刚才用来替换的羔羊= =//

//删除节点
BSTree Delete(BSTree pt,KeyType kx)
{
	BSTree ptr = pt;
	BSTree temp = nullptr;
	//寻找要删除的节点的位置↓
	if (!ptr)
		cout << "无此元素" << endl;
	else if (kx < ptr->key)		ptr->lchild = Delete(ptr->lchild, kx);		//切记更新指针
	else if (kx > ptr->key)		ptr->rchild = Delete(ptr->rchild, kx);
	else		//锁定要删除的节点位置
	{	
		//如果有两个好大儿
		if (ptr->lchild && ptr->rchild)
		{
			//找它的后继代替他
			temp = FindMin(ptr->rchild);
			ptr->key = temp->key;
			//删掉用来替换的节点
			ptr->rchild = Delete(ptr->rchild, ptr->key);
		}
		else		//如果有一个好大儿或者没有
		{
			temp = ptr;
			//孩子直接代替它爹的位置
			if (!ptr->lchild)
				ptr = ptr->rchild;
			else if (!ptr->rchild)
				ptr = ptr->lchild;
			free(temp);				//彻底删除
		}
	}
	return ptr;
}

全部= =//

#include <iostream>
#include <cstdlib>
#define T true
#define F false
typedef int KeyType;				//为了方便切换种类
using namespace std;
typedef struct node {
	KeyType key;
	struct node* lchild;			//左子树
	struct node* rchild;			//右子树
	struct node* parent;			//它老爹
}BstNode,*BSTree;
//购买一个节点供自己使用(奢侈脸)
BSTree BuyNode()		
{
	BSTree t = (BstNode*)malloc(sizeof(BstNode));
	if (nullptr == t)		exit(1);
	memset(t, 0, sizeof(BstNode));				//初始化节点
	return t;
}
//给大树造根
BSTree MakeRoot(KeyType kx)
{
	BSTree s = BuyNode();
	s->key = kx;
	return s;
}
//中序遍历二叉树,从小到大打印
//若想从大到小输出,只要把两次递归的顺序调换即可= =或者你也可以自己用个mode控制
void InOder(BSTree ptr)
{
	if (ptr != nullptr)
	{
		InOder(ptr->lchild);
		cout << ptr->key << " ";
		InOder(ptr->rchild);
	}
}
//插入节点
BSTree Insert(BSTree ptr, KeyType kx)
{
	if (ptr == nullptr)				//无根就造一个根出来
	{
		ptr = MakeRoot(kx);
		return ptr;
	}
	BSTree par = nullptr;			//记录上一个节点(父节点)
	BSTree p = ptr;					
	while (p != nullptr && p->key != kx)		//寻找位置并排查数据
	{
		par = p;
		p = kx < p->key ? p->lchild : p->rchild;
	}
	if (p != nullptr && p->key == kx)		return ptr;		//如果发现数据有重复
	p = BuyNode();					//奢侈一下
	p->key = kx;					
	p->parent = par;				//连接节点
	if (p->key < par->key)		par->lchild = p;			//反向连接
	else  par->rchild = p;
	return ptr;
}
//寻找树中的最小值
BSTree FindMin(BSTree ptr)
{
	BSTree t = ptr;
	//最小值一定在左下角
	while (t != nullptr && t->lchild != nullptr)		
		t = t->lchild;
	return t;

}
//寻找树中的最大值
BSTree FindMax(BSTree ptr)
{
	BSTree t = ptr;
	//最大值一定在右下角
	while (t != nullptr && t->rchild != nullptr)
		t = t->rchild;
	return t;
}
//寻找当前节点的前驱节点			
//就是数据比它小且离他最近		
BSTree Prev(BSTree pt)
{
	BSTree ptr = pt;
	if (ptr == nullptr)	return nullptr;
	//如果有左子树就在左子树里找
	if (ptr->lchild != nullptr)		return FindMax(ptr->lchild);		//比它小的数里找最大	
	else
	{
		//没有左子树就顺藤摸瓜向上找
		BSTree par = ptr->parent;
		while (par != nullptr && par->rchild != ptr)
		{
			ptr = par;
			par = ptr->parent;
		}
		return par;
	}
}
//寻找当前节点的后继节点			
//就是数据比它大且离他最近	
BSTree Next(BSTree pt)
{
	BSTree ptr = pt;
	if (ptr == nullptr)		return nullptr;
	if (ptr->rchild != nullptr)		return FindMin(ptr->rchild);		//比它大的数里找最小
	else
	{
		BSTree par = ptr->parent;
		while (par != nullptr && par->lchild != ptr)
		{
			ptr = par;
			par = ptr->parent;
		}
		return par;
	}
}
//删除节点
BSTree Delete(BSTree pt,KeyType kx)
{
	BSTree ptr = pt;
	BSTree temp = nullptr;
	//寻找要删除的节点的位置↓
	if (!ptr)
		cout << "无此元素" << endl;
	else if (kx < ptr->key)		ptr->lchild = Delete(ptr->lchild, kx);		//切记更新指针
	else if (kx > ptr->key)		ptr->rchild = Delete(ptr->rchild, kx);
	else		//锁定要删除的节点位置
	{	
		//如果有两个好大儿
		if (ptr->lchild && ptr->rchild)
		{
			//找它的后继代替他
			temp = FindMin(ptr->rchild);
			ptr->key = temp->key;
			//删掉用来替换的节点
			ptr->rchild = Delete(ptr->rchild, ptr->key);
		}
		else		//如果有一个好大儿或者没有
		{
			temp = ptr;
			//孩子直接代替它爹的位置
			if (!ptr->lchild)
				ptr = ptr->rchild;
			else if (!ptr->rchild)
				ptr = ptr->lchild;
			free(temp);				//彻底删除
		}
	}
	return ptr;
}



int main()
{
	int i;					
	BSTree root = nullptr;			//初始化根节点,必须写nullptr
	for (i = 10; i >= 0; --i)
		root = Insert(root, i);		//插入
	for (i = 20; i >= 0; --i)
		root = Insert(root, i);		//插入

	root = Delete(root, 5);			//删除
	root = Delete(root, 15);

	InOder(root);					//打印

	system("pause");
	return 0;
}

至于这个二叉搜索树会退化成单枝树的问题。。我们可以使用平衡二叉树和它融合来解决= =//

再见= =//

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值