C++实现搜索二叉树的基本操作

本文介绍使用C++模板实现二叉树的过程,并详细解释了如何处理模板嵌套问题。文章提供了完整的二叉树类定义及其实现,包括创建、遍历、查找、插入、删除等基本操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

敲代码中遇到的最大的一个坑是:如果原来有一个指针ptr1,指向的地址为0X,然后新声明一个指针ptr2,也让ptr2指向的地址为0X,对ptr2进行操作能够影响到0X地址,间接地影响指针ptr1,但本质上ptr1和ptr2是两个指针,因为发生的是拷贝,拷贝的对象当然是两个!一个具体的例子:执行“delete ptr2;ptr2=nullptr;”,ptr1指向的地址已经被销毁,但ptr1不会被置为nullptr,而依然指向原地址。也正是因为这个坑,代码里才有如此多的引用“&”,引用的本质是别名,而不是一个新的指针。

第二个坑是模板的嵌套。我想将struct TNode作为class BinTree的成员以提高封装性,这导致了模板类型的嵌套,具体的可以参考这篇博文:
C++模版中的typename关键字和嵌套依赖类型(依赖名称)

后续会继续补全树的相关操作,比如平衡树的调整~~~

更新~~平衡二叉树的基本实现请参考我的这一篇PAT Root of AVL Tree(C++实现)

#pragma once

#include<iostream>

using std::cout;
using std::cin;
using std::endl;

template<typename T>
class BinTree
{
public:
	struct TNode {
		T Data;//结点数据
		TNode* Left;//指向左子树
		TNode* Right;//指向右子树
	};
	using Root = TNode*;
	using Position = TNode*;
private:
	Root BT;//二叉树的根结点的地址

public:
	BinTree();
	~BinTree();
	void Destroy(Position& BT);
	const bool& IsEmpty();
	Position& GetRoot();
	void PreorderTraversal(Position BT);
	void InorderTraversal(Position BT);
	int GetHeight(Position BT);
	Position& Find(Position& BT, const T& X);
	Position& FindMax(Position& BT);
	Position& FindMin(Position& BT);
	Position Insert(Position& BT, const T& X);
	const bool& Delete(Position& BT, const T& X);
};

template<typename T>
BinTree<T>::BinTree() :BT{ nullptr }
{}

//销毁树
template<typename T>
void BinTree<T>::Destroy(Position& BT)
{
	if (!BT)
		;
	else {
		Destroy(BT->Left);
		Destroy(BT->Right);
		delete BT;
		BT = nullptr;
	}
}

template<typename T>
BinTree<T>::~BinTree()
{
	Destroy(this->GetRoot());
}

//判断是否为空树
template<typename T>
const bool& BinTree<T>::IsEmpty()
{
	if (BT)
		return false;
	else
		return true;
}

//返回根结点
template<typename T>
typename BinTree<T>::Position& BinTree<T>::GetRoot()
{
	return BT;
}


//递归求树的高度
template<typename T>
int BinTree<T>::GetHeight(Position BT)
{
	int HL{ 0 }, HR{ 0 };
	if (!BT)
		return 0;
	else {
		HL = GetHeight(BT->Left);
		HR = GetHeight(BT->Right);
		return (HL > HR ? HL : HR) + 1;
	}
}

//先序遍历
template<typename T>
void BinTree<T>::PreorderTraversal(Position BT)
{
	if (BT) {
		cout << BT->Data << ' ';
		PreorderTraversal(BT->Left);
		PreorderTraversal(BT->Right);
	}
}

//中序遍历
template<typename T>
void BinTree<T>::InorderTraversal(Position BT)
{
	if (BT) {
		InorderTraversal(BT->Left);
		cout << BT->Data << ' ';
		InorderTraversal(BT->Right);
	}
}


//递归查找元素
template<typename T>
typename BinTree<T>::Position& BinTree<T>::Find(Position& BT, const T& X)
{
	if (!BT)
		return BT;
	else {
		if (BT->Data > X)
			return Find(BT->Left, X);

		else if (BT->Data < X)
			return Find(BT->Right, X);
		else
			return BT;
	}
}


//递归查找最大元素
template<typename T>
typename BinTree<T>::Position& BinTree<T>::FindMax(Position& BT)
{
	if (!BT)
		return BT;
	else if (!BT->Right)
		return BT;
	else
		return FindMax(BT->Right);
}

//递归查找最小元素
template<typename T>
typename BinTree<T>::Position& BinTree<T>::FindMin(Position& BT)
{
	if (!BT)
		return BT;
	else if (!BT->Left)
		return BT;
	else
		return FindMin(BT->Left);
}

//插入元素
template<typename T>
typename BinTree<T>::Position BinTree<T>::Insert(Position& BT, const T& X)
{
	if (!BT) {
		BT = new TNode;
		BT->Data = X;
		BT->Left = nullptr;
		BT->Right = nullptr;
		return BT;
	}
	else if (X > BT->Data) {
		return Insert(BT->Right, X);
	}
	else if (X < BT->Data) {
		return Insert(BT->Left, X);
	}
	else
		return BT;
}

//删除结点
template<typename T>
const bool& BinTree<T>::Delete(Position& BT, const T& X)
{
	Position& removeBT = Find(BT, X);//找到要删除的元素
	if (!removeBT)
		return false;
	else {
		if (removeBT->Left && removeBT->Right) {//待删结点有两个孩子
			Position temp;
			temp = FindMin(removeBT->Right);//找到该结点右子树的最小结点
			removeBT->Data = temp->Data;
			delete temp;
			temp = nullptr;
			return true;
		}
		else if (removeBT->Left && !removeBT->Right) {//待删结点只有左孩子
			Position temp{ removeBT };
			removeBT = removeBT->Left;
			delete temp;
			temp = nullptr;
			return true;
		}
		else if (!removeBT->Left && removeBT->Right) {//待删结点只有右孩子
			Position temp{ removeBT };
			removeBT = removeBT->Right;
			delete temp;
			temp = nullptr;
			return true;
		}
		else {//待删结点没有孩子
			delete removeBT;
			removeBT = nullptr;
			return true;
		}
	}
}
#include<iostream>
#include"BinTree.h"

using namespace std;

int GetRandom(int X)//返回0到X-1之间的随机数
{
	return rand() % X;
}

int main()
{
	BinTree<int> BT1{};
	BT1.Insert(BT1.GetRoot(), 41);
	BT1.Insert(BT1.GetRoot(), 34);
	BT1.Insert(BT1.GetRoot(), 0);
	BT1.Insert(BT1.GetRoot(), 24);
	BT1.Insert(BT1.GetRoot(), 67);
	BT1.Insert(BT1.GetRoot(), 58);
	BT1.Insert(BT1.GetRoot(), 62);
	BT1.Insert(BT1.GetRoot(), 64);
	BT1.Insert(BT1.GetRoot(), 69);
	BT1.Insert(BT1.GetRoot(), 78);
	cout << BT1.GetHeight(BT1.GetRoot()) << '\n';
	BT1.PreorderTraversal(BT1.GetRoot());
	cout << '\n';
	BT1.InorderTraversal(BT1.GetRoot());
	BT1.Delete(BT1.GetRoot(), 64);
	cout << '\n';
	BT1.PreorderTraversal(BT1.GetRoot());
	cout<< '\n';
	cout << BT1.GetHeight(BT1.GetRoot()) << '\n';
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值