数据结构:树(2)——二叉搜索树相关算法

本文给出了树的相关算法,包括:二叉排序树的插入、搜索、结点删除。其中相关树的结构定义可以看本人另一篇博文:数据结构:树(1)——树相关算法.更多详细数据结构与算法实现可见本人github: DS

#include "tree.h"

//二叉排序树存储结构
typedef struct BSTNode
{
	int key;  //关键字域
	struct BSTNode* lchild, * rchild;//左右孩子指针
}BSTNode, * BSTree;

//二叉搜素/排序树的插入算法
BiTree Insert(Datatype x, BiTree &bst)
{
	if (!bst)  //若原树为空,生成并返回一个结点的二叉搜索树
	{
		bst = (BiTree)malloc(sizeof(BiTreeNode));
		bst->data = x;
		bst->lchild = NULL;
		bst->rchild = NULL;
	}
	else
	{
		if (x < bst->data)
		{
			bst->lchild = Insert(x, bst->lchild);  //递归插入左子树
		}
		else if(x>bst->data)
		{
			bst->rchild = Insert(x, bst->rchild);  //递归插入右子树
		}
		//else x已存在,什么都不做
	}
	return bst;
}

//二叉排序树的搜索
BiTree Find(Datatype x, BiTree BST)
{
	if (!BST)
	{
		return NULL;//查找失败
	}
	if (x > BST->data)
	{
		return Find(x, BST->rchild);  //在右子树中继续查找
	}
	else if (x < BST->data)
	{
		return Find(x, BST->lchild);  //在左子树中继续查找
	}
	else //x==BST.data
	{
		return BST;  //查找成功,返回找到结点的地址
	}
}

//二叉排序树的非递归寻找法
BiTree IterFind(Datatype x, BiTree BST)
{
	while (BST)
	{
		if (x > BST->data)
		{
			BST = BST->rchild;  //向右子树中移动,继续查找
		}
		else if (x < BST->data)
		{
			BST = BST->lchild;  //向左子树中移动,继续查找
		}
		else  //x==BST.data
		{
			return BST;  //查找成功,返回结点的找到结点的地址
		}
	}
	return NULL;
}

//查找最大元素
BiTree Findmax(BiTree BST)
{
	if (BST)
	{
		while (BST->rchild)
		{
			BST = BST->rchild;
		}
	}
	return BST;
}

//为了记住查找失败时访问的最后一个结点,改进查找算法如下
int SearchBST(BiTree bt, int key, BiTree* p, BiTree* q)
{
	/*在根节点bt所指二叉树中递归地查找关键字等于key的结点,若查找成功指针q指向该节点并返回1;否则
	指针q指向查找路径上最后一个访问结点并返回0,指针p指向bt的双亲,初始调用时值为NULL*/
	if (!bt)  //查找失败
	{
		*q = *p;
		return 0;
	}
	else if (key == bt->data)  //查找成功
	{
		*q = bt;
		return 1;
	}
	else if (key < bt->data)  //在左子树继续查找
	{
		*p = bt;
		return SearchBST(bt->lchild, key, p, q);
	}
	else  //在右子树继续查找
	{
		*p = bt;
		return SearchBST(bt->rchild, key, p, q);
	}
}

/*二叉排序树结点的删除*/
int DeleteBiTreeNode(BiTree* t, int key)
{
	BiTree p, f, s, q;
	if (SearchBST(*t, key, &f, &p) == 0)  //查找失败
	{
		return 0;
	}

	if (!(p->rchild))  //叶结点或只有左子树
	{
		if (f->lchild && f->lchild == p)
		{
			f->lchild = p->lchild;
		}
		else
		{
			f->rchild = p->lchild;
		}
	}
	else if(!(p->lchild))  //只有右子树
	{
		if (f->lchild && f->lchild == p)
		{
			f->lchild = p->rchild;
		}
		else
		{
			f->rchild = p->rchild;
		}
	}
	else  //左右子树均有
	{
		q = p;
		s = p->lchild;
		while (s->rchild)  //找到左子树的最大值,s指向该最大值,q指向最大值的父亲
		{
			q = s;
			s = s->rchild;
		}
		p->data = s->data;
		if (q != p)  //如果p的左子树有右子树
		{
			q->rchild = s->lchild;  //把最大数的左子树接到最大数的父亲
			free(s);
		}
		else  //p的左子树没有右子树
		{
			q->lchild = s->lchild;  //实际上s为p的左子树的根节点,q = p,把s的左子树接过来
			free(s);
		}
	}
	return 1;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值