数据结构之二叉搜索树


二叉搜索树

定义

优点

代码实现

#include<iostream>
using namespace std;
typedef int Elemtype;
typedef struct node
{
	Elemtype data;
	struct node* left, * right;
}BinNode,*BinTree;
//生成二叉查找树
//非递归建树
void CreateBinSerchTree(BinTree& node, Elemtype arr[], int n);
//递归建树
void Create_Bin_Serch_Tree(BinTree& node, Elemtype arr[], int n);
//插入数据
void Insert(BinTree& node, Elemtype key);
//查找所在的树高 count
void Serch(BinTree root, Elemtype key, int& height);
//删除所给数据的结点
BinTree DelNode(BinTree root, Elemtype key);
void InOrder(BinTree root);
//int main()
//{
//	BinTree root = NULL;
//	int arr[100];
//	int n;
//	cin >> n;
//	for (int i = 0; i < n; i++)
//		cin >> arr[i];
//	Create_Bin_Serch_Tree(root, arr, n);
//	InOrder(root);
//	cout << endl;
//	int key;
//	cin >> key;
//	DelNode(root, key);
//	InOrder(root);
//	return 0;
//}
//生成二叉查找树
//非递归建树
void CreateBinSerchTree(BinTree& node, Elemtype arr[], int n)
{
	node = new BinNode;								//赋空间存入首结点。
	node->data = arr[0];
	node->left = node->right = NULL;
	int flag = 2;									//定义flag来标记结点是该存在左结点还是在右结点。
	for (int i = 1; i < n; i++)						//开始存入数组中的数据。
	{
		flag = 2;					
		BinTree p = node, q = node, r = new BinNode;//将数组中的数据存入生成的新结点r,p是初始化为node初始结点,q
		r->data = arr[i];							//用于标记p的父节点。
		r->left = r->right = NULL;
		while (p != NULL)
		{
			q = p;									//提前将p赋给q,这样p在移动到左右结点时q就是p的父节点了。
			if (p->data < arr[i])					//待插入结点值大于结点p,p进入右结点。
			{
				p = p->right;
				flag = 1;							//flag置为1,说明p进入了右结点。
			}
			else if (p->data > arr[i])				//待插入结点值大于结点p,p进入右结点。
			{
				p = p->left;
				flag = 0;							//flag置为0,说明p进入了左结点。
			}
		}
		if (flag)									//根据flag判断该插入的结点是在左还是在右。
			q->right = r;
		else
			q->left = r;
	}
}
//递归建树
//将数据插入到正确结点处
void Insert(BinTree& node, Elemtype key)
{
	if (node == NULL)						//此时结点为空,说明已经父节点符合搜索树的条件
	{										//将生成的空间插入。
		node = new BinNode;
		node->data = key;
		node->left = node->right = NULL;
	}
	else if (node->data > key)				//结点值大于待插入的key,因此递归到左孩子结点进行比较。
		Insert(node->left, key);
	else									//结点值小于待插入的key,递归到右孩子结点进行比较。
		Insert(node->right, key);
}
void Create_Bin_Serch_Tree(BinTree& node, Elemtype arr[], int n)
{
	node = new BinNode;						//首节点赋空间存入待整理数组的首元素。
	node->data = arr[0];
	node->left = node->right = NULL;
	for (int i = 1; i < n; i++)
	{
		Insert(node, arr[i]);				//将数组所有元素都插入到搜索树中。
	}
}
//查找key数据所在的树高 height
void Serch(BinTree root, Elemtype key, int& height)
{
	if (root == NULL)						//遇见了空结点,说明进行递归比较后始终没有
	{										//找到key,因此该搜索树中不存在key,将height赋-1。
		height = -1;
		return;
	}
	if (root->data == key)					//找到了对应key,返回此节点树高。
	{
		height++;
		return;
	}
	else if (root->data > key)
		Serch(root->left, key, height);		//递归查询左子树。
	else
		Serch(root->right, key, height);	//递归查询右子树。
}
//删除所给数据的结点
//采用递归实现
/*
root为二叉搜索树结点,key为待删除结点的值
*/
BinTree DelNode(BinTree root, Elemtype key)
{
	if (root == NULL)						//当root为NULL时说明经过遍历查找 最终并没有
		return root;						//找到key值对应的结点,因此直接返回NULL即可。
	if (key < root->data)
	{
		root->left = DelNode(root->left, key);//key值小于当前结点,说明key在root结点的左子树。
	}
	else if (key > root->data)
	{
		root->right = DelNode(root->right, key);//key值大于当前结点,说明key在root结点的右子树。
	}
	else										//此时key值等于当前结点因此进行删除操作。
	{
		if (root->left == NULL)					//左节点为空,说明该结点仅有右子树或者没有子节点。
		{
			BinTree temp = root->right;			//temp保存root结点的右子树并返回。
			delete root;						//释放root结点。
			return temp;						//保存的temp结点会退回到上一层递归的root->left=(或者root->right=)处
												//这样就完成了删除root结点而将搜索树也保持了连接。
		}
		else if (root->right == NULL)			//右节点为空,说明该结点仅有左子树或者没有字节的。
		{
			BinTree temp = root->left;			//temp保存root结点的左子树并返回。
			delete root;						//释放root结点。
			return temp;						//保存的temp结点会退回到上一层递归的root->left=(或者root->right=)处
												//这样就完成了删除root结点而将搜索树也保持了连接。
		}
		BinTree p = root->right, temp = NULL;	//函数运行到此处说明待删除的root结点拥有两个子节点,因此要进行特殊处理。
		while (p->left != NULL)					//对于待删除结点拥有两个子节点的情况,必须要知道:删除该结点后它的左子树
		{										//最大结点或者右子树最小结点需要置换到它的位置,这样才能保住二叉搜索树的
			p = p->left;						//结构不被破坏。

												//在此处while循环中就是为了寻找到该结点的右子树中的最小结点,根据搜索树
		}										//性质,左子树都要小于该结点,因此先右再左,就能找到满足的结点了。
		temp = p;
		root->data = temp->data;				//将找到的结点换到key值结点的位置。
		root->right = DelNode(root->right, temp->data);//同时删除找到的p结点,而p结点必定是只有一个或者没有子节点的,将
												//root结点的右子树连接到删除后的正常路径上。
	}
	return root;								//运行到此处说明待删除结点有两个子节点并已经完成了删除操作,将此结点返回
												//保证二叉树正常连接即可
}

//中序遍历
void InOrder(BinTree root)
{
	if (root == NULL)
		return;
	InOrder(root->left);
	cout << root->data << " ";
	InOrder(root->right);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值