面试题之二叉树

本文详细介绍了二叉树的各种操作实现,包括递归与非递归遍历、节点查找、高度计算等,并提供了完整的C++代码示例。

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

#include<iostream>
#include<stack>
#include<queue>
using namespace std;

template<typename T>
struct BinaryTreeNode
{
	BinaryTreeNode(const T& data = T())
	:_data(data)
	, _LeftChild(NULL)
	, _RightChild(NULL)
	{}
	T _data;
	BinaryTreeNode<T>* _LeftChild;
	BinaryTreeNode<T>* _RightChild;
};

template<typename T>
class BinaryTree
{
public:
	BinaryTree()
		:_pRoot(NULL)
	{}
	BinaryTree(T *array, size_t size)//构造函数
		:_pRoot(NULL)
	{
		size_t index = 0;
		CreatBinaryTree(array, _pRoot, size, index);
	}
	BinaryTree(const BinaryTree<T>& b)//拷贝构造函数
	{
		_pRoot = CopyBinaryTree(b._pRoot);
	}
	BinaryTree<T>& operator = (BinaryTree<T>& b)//赋值运算符重载
	{
		if (this != &b)//判断是否自己给自己赋值
		{
			Destroy(_pRoot);//删除二叉树 
			_pRoot = CopyBinaryTree(b._pRoot);
		}
		return this;
	}
	~BinaryTree()//析构函数
	{
		Destroy(_pRoot);
	}
	void Pre_order()//递归前序排序
	{
		cout << "递归前序:";
		PreorderBinaryTree(_pRoot);
	}
	void In_order()//递归中序排序
	{
		cout << "递归中序:";
		InorderBinaryTree(_pRoot);
	}
	void Post_order()//递归后序排序
	{
		cout << "递归后序:";
		PostorderBinaryTree(_pRoot);
	}
	void Perorder_Binary()//循环前序排序
	{
		cout << "循环前序:";
		Preorder_BinaryTree(_pRoot);
	}
	void Inorder_Binary()//循环中序排序
	{
		cout << "循环中序:";
		Inorder_BinaryTree(_pRoot);
	}
	void Postorder_Binary()//循环后序排序
	{
		cout << "循环后序:";
		Postorder_BinaryTree(_pRoot);
	}
	void Leave_Binary()//分层遍历
	{
		cout << "分层遍历:";
		Leave_BinaryTree(_pRoot);
	}
	void MirrorBinaryTree()//镜像二叉树
	{
		cout << "镜像二叉树:";
		_MirrorBinaryTree(_pRoot);
	}
	BinaryTreeNode<T>* Find(const T& data)//寻找某一节点
	{
		return FindBinaryTree(_pRoot, data);
	}
	BinaryTreeNode<T>* Getparent(const T& data)//寻找某节点双亲节点
	{
		cout << "找到的双亲是:";
		BinaryTreeNode<T>* pCur = Find(data);
		return _Getparent(_pRoot, pCur);
	}
	size_t Height()//获取树的高度
	{
		cout << "树的高度是:";
		return _Height(_pRoot);
	}
	size_t GetNodenumber()//获取节点树
	{
		cout << "树的节点数是:";
		return _GetNodeNumber(_pRoot);
	}

	size_t GetLeaveNodeNumber()//获取叶节点的个数
	{
		cout << "树的叶子节点数是:";
		return _GetLeaveNodeNomber(_pRoot);
	}

	size_t GetLevelKNodeNumber()//获取第K层的节点数
	{
		cout << "第K层的节点数是:";
		return _GetLevelKNoderNumber(_pRoot, 2);
	}

	bool BalanceBinaryTree()
	{
		cout << "该二叉树是否为平衡二叉树?:";
		return _BalanceBinaryTree(_pRoot);
	}

	
private:
	void CreatBinaryTree(T *array, BinaryTreeNode<T>*& pRoot, size_t size, size_t& index)//函数递归,创建二叉树
	{
		if (index < size &&  '#' != array[index])
		{
			pRoot = new BinaryTreeNode<T>(array[index]);
			CreatBinaryTree(array, pRoot->_LeftChild, size, ++index);
			CreatBinaryTree(array, pRoot->_RightChild, size, ++index);
		}
	}
	BinaryTreeNode<T>* CopyBinaryTree(BinaryTreeNode<T>* pRoot)//函数递归,拷贝构造函数
	{
		BinaryTreeNode<T>* pNewRoot = NULL;
		if (NULL != pRoot)
		{
			pNewRoot = new BinaryTreeNode<T>(pRoot->_data);
			pNewRoot->_LeftChild = CopyBinaryTree(pRoot->_LeftChild);//拷贝构造左子树
			pNewRoot->_RightChild = CopyBinaryTree(pRoot->_RightChild);//拷贝构造右子树
		}
		return pNewRoot;//返回该树
	}

	void Destroy(BinaryTreeNode<T>* pRoot)//函数递归,删除二叉树。
	{
		if (pRoot)//如果根节点不为空
		{
			Destroy(pRoot->_LeftChild);//遍历该节点的左孩子
			Destroy(pRoot->_RightChild);//遍历该节点的右孩子
			delete pRoot;//删除该节点
			pRoot = NULL;
		}
	}
	void PreorderBinaryTree(BinaryTreeNode<T>* pRoot)//递归前序排序
	{
		if (NULL == pRoot)
			return;
		cout << pRoot->_data << " ";
		PreorderBinaryTree(pRoot->_LeftChild);
		PreorderBinaryTree(pRoot->_RightChild);
	}

	void InorderBinaryTree(BinaryTreeNode<T>* pRoot)//递归中序排序
	{
		if (NULL == pRoot)
			return;
		InorderBinaryTree(pRoot->_LeftChild);
		cout << pRoot->_data << " ";
		InorderBinaryTree(pRoot->_RightChild);
	}

	void PostorderBinaryTree(BinaryTreeNode<T>* pRoot)//递归后序排序
	{
		if (NULL == pRoot)
			return;
		PostorderBinaryTree(pRoot->_LeftChild);
		PostorderBinaryTree(pRoot->_RightChild);
		cout << pRoot->_data << " ";
	}

	void Preorder_BinaryTree(BinaryTreeNode<T>* pRoot)//循环前序排序(栈)
	{
		if (NULL == pRoot)
			return;
		stack<BinaryTreeNode<T>* > s;
		s.push(pRoot);
		while (!s.empty())//判断栈是否为空 
		{
			BinaryTreeNode<T>* pTop = s.top();//创建指针指向栈顶
			cout << pTop->_data << " ";//访问该节点
			s.pop();//该节点出栈
			if (pTop->_RightChild)
				s.push(pTop->_RightChild);//右孩子不为空,入栈
			if (pTop->_LeftChild)
				s.push(pTop->_LeftChild);//左孩子不为空,入栈
		}
	}

	void Inorder_BinaryTree(BinaryTreeNode<T>* pRoot)//循环中序排序(栈)
	{
		if (NULL == pRoot)
			return;
		stack<BinaryTreeNode<T>* > s;//创建栈
		BinaryTreeNode<T> *pCur = pRoot;//根节点标记
		while (!s.empty() || pCur)//栈不为空或根节点存在
		{
			while (pCur)//根节点存在
			{
				s.push(pCur);//根节点入栈
				pCur = pCur->_LeftChild;//根节点指向左孩子
			}
			BinaryTreeNode<T> *pTop = s.top();//标记栈顶元素
			cout << pTop->_data << " ";//访问栈顶
			s.pop();//出栈
			pCur = pTop->_RightChild;//根节点指向右孩子
		}
	}

	void Postorder_BinaryTree(BinaryTreeNode<T>* pRoot)//循环后序排序(栈)
	{
		if (NULL == pRoot)
			return;
		stack<BinaryTreeNode<T>* > s;//创建栈
		BinaryTreeNode<T> *pCur = pRoot;//根节点标记
		BinaryTreeNode<T> *pVir = NULL;//标记访问过的节点
		while (!s.empty() || pCur)//栈不为空或根节点存在
		{
			while (pCur)//根节点存在
			{
				s.push(pCur);//根节点入栈
				pCur = pCur->_LeftChild;//根节点指向左孩子
			}
			BinaryTreeNode<T>* pTop = s.top();//标记栈顶元素
			if (NULL == pTop->_RightChild || pTop->_RightChild == pVir)//右孩子不存在或者右孩子已经被访问
			{
				cout << pTop->_data << " ";//访问该节点
				pVir = pTop;//标记访问过的节点
				s.pop();//出栈
			}
			else
				pCur = pTop->_RightChild;//根节点指向右孩子
		}
	}

	void Leave_BinaryTree(BinaryTreeNode<T>* pRoot)//分层排序
	{
		if (NULL == pRoot)
			return;
		queue<BinaryTreeNode<T> *> q;
		q.push(pRoot);
		while (!q.empty())
		{
			BinaryTreeNode<T> *pNode = q.front();
			q.pop();
			cout << pNode->_data << " ";
			if (pNode->_LeftChild != NULL)
				q.push(pNode->_LeftChild);
			if (pNode->_RightChild != NULL)
				q.push(pNode->_RightChild);
		}
	}

	void _MirrorBinaryTree(BinaryTreeNode<T>* pRoot)//镜像二叉树
	{
		if (NULL == pRoot)
			return;
		BinaryTreeNode<T>* pTmp = pRoot->_LeftChild;
		pRoot->_LeftChild = pRoot->_RightChild;
		pRoot->_RightChild = pTmp;
		cout << pRoot->_data << " ";
		_MirrorBinaryTree(pRoot->_LeftChild);
		_MirrorBinaryTree(pRoot->_RightChild);
	}

	BinaryTreeNode<T>* FindBinaryTree(BinaryTreeNode<T>* pRoot, const T& data)//寻找某一节点
	{
		if (NULL == pRoot)
			return NULL;
		if (data == pRoot->_data)
			return pRoot;
		if (FindBinaryTree(pRoot->_LeftChild, data))//左子树寻找到节点
		{
			return FindBinaryTree(pRoot->_LeftChild, data);
		}
		else
			return FindBinaryTree(pRoot->_RightChild, data);//右子树寻找到节点
	}
	BinaryTreeNode<T>* _Getparent(BinaryTreeNode<T>* pRoot, BinaryTreeNode<T>* pCur)//寻找双亲节点
	{
		BinaryTreeNode<T>* parent = NULL;//定义指针指向双亲节点
		if (NULL == pRoot)
			return NULL;
		if (NULL == pCur || pRoot == pCur)
			return NULL;
		if (pRoot->_LeftChild == pCur || pRoot->_RightChild == pCur)
			return pRoot;
		if (parent == _Getparent(pRoot->_LeftChild, pCur))
			return parent;
		else
			return _Getparent(pRoot->_RightChild, pCur);
	}
	size_t _Height(BinaryTreeNode<T>* pRoot)//获取树的高度
	{
		if (NULL == pRoot)
			return 0;
		if (NULL == pRoot->_LeftChild && NULL == pRoot->_RightChild)
			return 1;
		size_t LeftHeight = _Height(pRoot->_LeftChild);
		size_t RightHeight = _Height(pRoot->_RightChild);
		return (LeftHeight > RightHeight) ? LeftHeight + 1 : RightHeight + 1;
	}
	size_t _GetNodeNumber(BinaryTreeNode<T>* pRoot)//获取二叉树的节点数
	{
		if (NULL == pRoot)
			return 0;
		return _GetNodeNumber(pRoot->_LeftChild) + _GetNodeNumber(pRoot->_RightChild) + 1;
	}
	size_t _GetLeaveNodeNomber(BinaryTreeNode<T>* pRoot)//获取叶节点的个数
	{
		if (NULL == pRoot)
			return 0;
		if (pRoot->_LeftChild == NULL && pRoot->_RightChild == NULL)
			return 1;
		size_t LeftNumber = _GetLeaveNodeNomber(pRoot->_LeftChild);
		size_t RightNumber = _GetLeaveNodeNomber(pRoot->_RightChild);
		return(LeftNumber + RightNumber);
	}

	size_t _GetLevelKNoderNumber(BinaryTreeNode<T>* pRoot, size_t K)//获取第k层节点数
	{
		if (NULL == pRoot || K <= 0)
			return 0;
		if (NULL != pRoot && K == 1)
			return 1;
		return _GetLevelKNoderNumber(pRoot->_LeftChild, K - 1) + _GetLevelKNoderNumber(pRoot->_RightChild, K - 1);
	}

	bool _BalanceBinaryTree(BinaryTreeNode<T>* pRoot)
	{
		if (pRoot == NULL)
			return false;
		if (pRoot->_LeftChild == NULL && pRoot->_RightChild == NULL)
			return true;

		int HeightLeft = _Height(pRoot->_LeftChild);
		int HeightRight = _Height(pRoot->_RightChild);
		int count = abs(HeightRight - HeightLeft);//绝对值
		if (count <= 1)
			return true;
		else
			return false;
	}
private:
	BinaryTreeNode<T> *_pRoot;
};

void FunTest()
{
	char *array = "abd###ce##f";
	BinaryTree<char> s(array, strlen(array));
	//cout << s.Find('b') << endl;//寻找某一节点
	s.Pre_order();//递归前序排序
	cout << endl;
	s.In_order();//递归中序排序
	cout << endl;
	s.Post_order();//递归后序排序
	cout << endl;
	s.Perorder_Binary();//循环前序排序
	cout << endl;
	s.Inorder_Binary();//循环中序排序
	cout << endl;
	s.Postorder_Binary();//循环后序排序
	cout << endl;
	s.Leave_Binary();//分层遍历
	cout << endl;
	s.MirrorBinaryTree();//镜像二叉树
	cout << endl;
	cout << "找到的节点是:";
	cout << s.Find('a') << endl;//寻找某一节点
	cout << s.Getparent('c') << endl;//寻找该节点的双亲节点
	cout << s.Height() << endl;//获取该树的高度
	cout << s.GetNodenumber() << endl;//获取该树的节点数
	cout << s.GetLeaveNodeNumber() << endl;//获取叶节点数
	cout << s.GetLevelKNodeNumber() << endl;//获取第k层节点数
	cout << s.BalanceBinaryTree() << endl;//平衡二叉树
	cout << endl;
}
int main()
{
	FunTest();
	system("pause");
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值