12.动态查找-二叉排序树

实验12 动态查找 二叉排序树

代码

#include <iostream>

using namespace std;

#define ENDFLAG '#'

struct ElemType
{
	char key;
	// Other info
};

struct BSTNode
{
	ElemType data;			  //结点数据域
	BSTNode *lchild, *rchild; //左右孩子指针
};

using BSTree = BSTNode *;

// 二叉排序树的递归查找
BSTree SearchBST(BSTree T, char key)
{
	//在根指针T所指二叉排序树中递归地查找某关键字等于key的数据元素
	//若查找成功,则返回指向该数据元素结点的指针,否则返回空指针
	if (!T || T->data.key == key)
		return T; //查找结束
	else if (key < T->data.key)
		return SearchBST(T->lchild, key); //在左子树中继续查找
	else
		return SearchBST(T->rchild, key); //在右子树中继续查找
}

// 二叉排序树的插入
void InsertBST(BSTree &T, ElemType e)
{
	//当二叉排序树T中不存在关键字等于e.key的数据元素时,则插入该元素
	if (!T)
	{										   //找到插入位置,递归结束
		BSTNode *node = new BSTNode;		   //生成新结点*S
		node->data = e;						   //新结点*S的数据域置为e
		node->lchild = node->rchild = nullptr; //新结点*S作为叶子结点
		T = node;							   //把新结点*S链接到已找到的插入位置
	}
	else if (e.key < T->data.key)
		InsertBST(T->lchild, e); //插入左子树
	else if (e.key > T->data.key)
		InsertBST(T->rchild, e); //插入右子树
}

// 二叉排序树的创建
void CreateBST(BSTree &T)
{
	T = nullptr;
	ElemType e;
	cin >> e.key;
	while (e.key != ENDFLAG) //ENDFLAG为自定义常量,作为输入结束标志
	{
		InsertBST(T, e); //将此结点插入二叉排序树T中
		cin >> e.key;
	}
}

// 从二叉排序树T中删除关键字等于key的结点
void DeleteBST(BSTree &T, char key)
{
	BSTree target = T;		 // 要删除的结点
	BSTree parent = nullptr; // 要删除结点的父节点

	while (target) // 从根开始查找关键字等于key的结点
	{
		if (target->data.key == key)
			break; // 找到了

		parent = target; // 记录父节点
		if (target->data.key > key)
			target = target->lchild;
		else
			target = target->rchild;
	}

	if (!target)
		return; // 找不到要删结点

	// 被删结点左右子树均不空
	if ((target->lchild) && (target->rchild))
	{
		// 找到待删除结点中序遍历的前驱结点, 即左子树中最右下的结点
		BSTree pre = target->lchild;	// 前驱结点
		BSTree parent_of_pre = nullptr; // 前驱结点的父节点
		while (pre->rchild)
		{
			parent_of_pre = pre;
			pre = pre->rchild;
		}
		target->data = pre->data;			 // 偷天换日, 把前驱结点的值扔到待删除的结点里面
		parent_of_pre->rchild = pre->lchild; // 如果前驱结点有左子树(不可能有右子树), 把它换到前驱结点的位置(右边)
		delete pre;							 // 把前驱删掉即可
		return;
	}

	// 其它两种情况
	BSTree to_replace = nullptr;
	if (!target->lchild) // 如果要被删除的结点没有左子树, 用其右子树代替它的位置
		to_replace = target->rchild;
	else if (!target->rchild) // 如果没有右子树, 用左子树代替它的位置
		to_replace = target->lchild;

	if (!parent) // 没有父节点就取代根结点位置
		T = to_replace;
	else if (target == parent->lchild) // 如果要被删除的结点是左边的
		parent->lchild = to_replace;   // 取代左边的位置
	else if (target == parent->rchild) // 如果被删除结点是右边的
		parent->rchild = to_replace;   // 取代右边的位置

	delete target; // 删掉目标结点
}

// 中序遍历
void InOrderTraverse(BSTree &T)
{
	if (T)
	{
		InOrderTraverse(T->lchild);
		cout << T->data.key << '\t';
		InOrderTraverse(T->rchild);
	}
}

int main()
{
	BSTree T;
	cout << "请输入若干字符(#表示输入结束): ";
	CreateBST(T);
	cout << "中序遍历结果为" << endl;
	InOrderTraverse(T);
	cout << endl;

	char key; //待查找或待删除内容
	cout << "请输入待查找字符: ";
	cin >> key;
	if (SearchBST(T, key))
		cout << "找到字符" << key << endl;
	else
		cout << "未找到" << key << endl;

	cout << "请输入待删除的字符: ";
	cin >> key;
	DeleteBST(T, key);
	cout << "中序遍历结果为" << endl;
	InOrderTraverse(T);
	cout << endl;
}

截图

posted @ 2020-12-01 19:11  zaxtyson  阅读(242)  评论(0编辑  收藏  举报