#pragma once
#include<iostream>
#include<windows.h>
#include<string.h>
#include<queue>
#include<stack>
using namespace std;
// 孩子表示法
template<class T>
struct BinaryTreeNode
{
BinaryTreeNode(const T& value)
: _value(value)
, _pLeft(NULL)
, _pRight(NULL)
{}
T _value;
BinaryTreeNode<T>* _pLeft; // 左孩子
BinaryTreeNode<T>* _pRight; // 右孩子
};
//创建(遍历)二叉树的时间复杂度O(N)
template<class T>
class BinaryTree
{
typedef BinaryTreeNode<T> Node;
public:
BinaryTree()
: _pRoot(NULL)
{}
BinaryTree(const T arr[], size_t size, const T& invalid)
{
size_t index = 0;
_CreateBinaryTree(_pRoot, arr, size, index, invalid);
}
BinaryTree(const BinaryTree<T>& bt)
{
_pRoot = _CopyBirnaryTree(bt._pRoot);
}
BinaryTree<T>& operator=(const BinaryTree<T>& bt)
{
if (this != &bt)
{
_DestroyBinaryTree(_pRoot);
_pRoot=_CopyBirnaryTree(bt._pRoot);
}
return *this;
}
~BinaryTree()
{
_DestroyBinaryTree(_pRoot);
}
///////////////////////////////////////////////////////////////
void PreOrder()
{
cout << "PreOrder:" << endl;
_PreOrder(_pRoot);
cout << endl;
}
void PreOrder_Nor()
{
cout << "PreOrder_Nor:" << endl;
_PreOrder_Nor(_pRoot);
cout << endl;
}
void InOrder()
{
cout << "InOrder:" << endl;
_InOrder(_pRoot);
cout << endl;
}
void InOrder_Nor()
{
cout << "InOrder_Nor:" << endl;
_InOrder_Nor(_pRoot);
cout << endl;
}
void PostOrder()
{
cout << "PostOrder:" << endl;
_PostOrder(_pRoot);
cout << endl;
}
void PostOrder_Nor()
{
cout << "PostOrder_Nor:" << endl;
_PostOrder_Nor(_pRoot);
cout << endl;
}
void LevelOrder()//******考点********队列***
{
cout << "LevelOrde:" << endl;
_LevelOrder(_pRoot);
cout << endl;
}
Node* Find(const T& value)
{
return _Find(_pRoot, value);
}
//二叉树中和为某一值的路径
void FindPath(size_t WantSum)
{
size_t Cursum = 0;
vector<int>path;
_FindPath(_pRoot, WantSum, path, Cursum);
}
Node* Parent(Node* pCur)
{
return _Parent(_pRoot, pCur);
}
Node* GetLeftChild(Node* pCur)
{
return (pCur == NULL) ? NULL : pCur->_pLeft;
}
Node* GetRightChild(Node* pCur)
{
return (pCur == NULL) ? NULL : pCur->_pRight;
}
size_t Height()
{
return _Height(_pRoot);
}
size_t GetLeefCount()
{
return _GetLeefCount(_pRoot);
}
size_t GetKLevelCount(size_t k)
{
return _GetKLevelCount(_pRoot, k);
}
void BinaryMirror_Nor()
{
return _BinaryMirror_Nor();
}
void BinaryMirror()
{
return _BinaryMirror(_pRoot);
}
private:
// 根—左—右 —>构造二叉树
void _CreateBinaryTree(Node* &pRoot, const T arr[], size_t size, size_t& index, const T& invalid)
{
if (index < size&&arr[index] != invalid)//顺序不能颠倒,防止越界访问
{
//创建根节点
pRoot = new Node(arr[index]);
//创建左孩子节点
_CreateBinaryTree(pRoot->_pLeft, arr, size, ++index, invalid);
//创建右孩子节点(看不见右孩子创建节点过程)
_CreateBinaryTree(pRoot->_pRight, arr, size, ++index, invalid);
}
}
// pRoot-->被拷贝树的根节点
Node* _CopyBirnaryTree(Node* pRoot)
{
Node* pNewRoot = NULL;
if (pRoot)
{
pNewRoot = new Node(pRoot[0]);//拷贝根节点
pNewRoot->_pLeft = _CopyBirnaryTree(pRoot->_pLeft); //拷贝左子树
pNewRoot->_pRight = _CopyBirnaryTree(pRoot->_pRight);//拷右左子树
}
return pNewRoot;
}
void _DestroyBinaryTree(Node*& pRoot)
{
if (pRoot)
{
_DestroyBinaryTree(pRoot->_pLeft);
_DestroyBinaryTree(pRoot->_pRight);
delete pRoot;
pRoot = NULL;
}
}
////////////////////////////////////////////////////////////////
//前序遍历递归
// 前序:访问根节点--->访问根节点的左子树--->访问根节点的右子树
void _PreOrder(Node* pRoot)
{
if (pRoot)
{
cout << pRoot->_value << " ";
_PreOrder(pRoot->_pLeft);
_PreOrder(pRoot->_pRight);
}
}
//前序遍历非递归
void _PreOrder_Nor(Node*pRoot)
{
if (NULL == pRoot)
return;
stack<Node*>s;
s.push(pRoot);
while (!s.empty())
{
Node*pCur = s.top();
cout << pCur->_value << " ";
s.pop();
if (pCur->_pRight)
s.push(pCur->_pRight);
if (pCur->_pLeft)
s.push(pCur->_pLeft);
}
}
//中序遍历递归
void _InOrder(Node* pRoot)
{
if (pRoot)
{
_InOrder(pRoot->_pLeft);
cout << pRoot->_value << " ";
_InOrder(pRoot->_pRight);
}
}
//中序遍历非递归
void _InOrder_Nor(Node*pRoot)
{
if (NULL == pRoot)
return;
stack<Node*>s;
Node*pCur = pRoot;
while (pCur || !s.empty())
{
while (pCur)
{ // 找到最左边的孩子,并把所经过路径的结点保存下来
s.push(pCur);
pCur = pCur->_pLeft;
}
//出了内层循环,pCur为空,栈顶元素为最左边的孩子
pCur = s.top();
cout << pCur->_value << " ";
s.pop();
pCur = pCur->_pRight;
}
}
// 后序遍历:遍历根的左子树-->遍历根的右子树-->遍历根节点
void _PostOrder(Node* pRoot)
{
if (pRoot)
{
_PostOrder(pRoot->_pLeft);
_PostOrder(pRoot->_pRight);
cout << pRoot->_value << " ";
}
}
//后序遍历非递归
void _PostOrder_Nor(Node*pRoot)
{
if (NULL == pRoot)
return;
stack<Node*>s;
Node*pCur = pRoot;
Node*Prev = NULL;//保存上次入栈的结点
while (pCur || !s.empty())
{
while (pCur)
{ // 找到最左边的孩子,并把所经过路径的结点保存下来
s.push(pCur);
pCur = pCur->_pLeft;
}
Node*pTop = s.top();
if (NULL == pTop->_pRight || Prev == pTop->_pRight)//没有Prev == pTop->_pRight会4256666666......死循环下去
{
cout << pTop->_value << " ";
Prev = pTop; //保存上次入栈的结点
s.pop();
}
else
{
pCur = pTop;//pCur在while出来之后为NULL,所以要更新pCur的值,少了这句,崩溃
pCur = pCur->_pRight;
}
}
}
// 层序遍历
void _LevelOrder(Node*pRoot)//******考点********队列***
{
if (NULL == pRoot)
return;
queue<Node*>q;
q.push(pRoot);//保存的是结点的地址,地址出了队列,但是树并没有改变
while (!q.empty())
{
Node*pcur = q.front();
cout << pcur->_value << " ";
if (pcur->_pLeft)//左不为空入队列
{
q.push(pcur->_pLeft);
}
if (pcur->_pRight)//右不为空入队列
{
q.push(pcur->_pRight);
}
q.pop();
}
cout << endl;
}
//二叉树中和为某一值的路径
void _FindPath(Node*pRoot, size_t WantSum, vector<int>&path, size_t CurSum)
{
CurSum += pRoot->_value;
path.push_back(pRoot->_value);
//如果是叶子结点,并且路径上结点的和等于输入的值,打印这条路径
if (CurSum == WantSum&&NULL == pRoot->_pLeft&&NULL == pRoot->_pRight)
{
cout << WantSum << "path is found:" << endl;
vector<int>::iterator it = path.begin();
while (!path.empty() && it != path.end())
{
cout << *it << " ";
it++;
}
cout << endl;
}
if (pRoot->_pLeft)
{
_FindPath(pRoot->_pLeft, WantSum, path, CurSum);
}
if (pRoot->_pRight)
{
_FindPath(pRoot->_pRight, WantSum, path, CurSum);
}
//在返回父节点之前,在路径上删除当前节点
path.pop_back();
}
//树中查找一个节点
Node* _Find(Node* pRoot, const T& value)
{
Node*pCur = NULL;
if (NULL == pRoot)
return NULL;
if (pRoot->_value == value)
{
return pRoot;
}
pCur = _Find(pRoot->_pLeft, value);
if (NULL!=pCur)
return pCur;
return _Find(pRoot->_pRight, value);
}
//求一个节点的双亲
Node* _Parent(Node* pRoot, Node* pCur)
{
if (NULL == pRoot)//树空
return NULL;
if (NULL==pRoot->_pLeft&&NULL == pRoot->_pRight)//只有一个节点
return NULL;
if (pRoot == pCur)
return NULL;//所找结点刚好为根结点
if (pCur == pRoot->_pLeft || pCur == pRoot->_pRight)
return pRoot;
Node*parent = NULL;
parent = _Parent(pRoot->_pLeft, pCur);//从左子树中找
if (NULL != pCur)
return pCur;
return _Parent(pRoot->_pLeft, pCur);//从右子树中找
}
//求二叉树的高度
size_t _Height(Node* pRoot)
{
if (NULL == pRoot)
return 0;
if (NULL == pRoot->_pLeft&&NULL == pRoot->_pRight)//一个节点
return 1;
size_t Left_Height=_Height(pRoot->_pLeft);//左子树的高度
size_t Right_Height = _Height(pRoot->_pRight);//右子树的高度
return Left_Height > Right_Height ? Left_Height + 1 : Right_Height + 1;
}
//求叶子节点的个数
size_t _GetLeefCount(Node* pRoot)
{
if (NULL == pRoot)
return 0;
if (NULL == pRoot->_pLeft&&NULL == pRoot->_pRight)//一个节点
return 1;
size_t Left_LeefCount=_GetLeefCount(pRoot->_pLeft);
size_t Right_LeefCount = _GetLeefCount(pRoot->_pRight);
return Left_LeefCount + Right_LeefCount;
}
//求第K层节点的个数
size_t _GetKLevelCount(Node* pRoot, size_t k)
{
if (NULL == pRoot || k<1)//此处省略了K>Height(_pRoot),因为大于树的
return 0; //高度时返回0
if (k == 1)
return 1;
size_t LeftKLevelCount=_GetKLevelCount(pRoot->_pLeft, k - 1);
size_t RighttKLevelCount = _GetKLevelCount(pRoot->_pRight, k - 1);
return LeftKLevelCount + RighttKLevelCount;
}
//二叉树的镜像—递归
void _BinaryMirror(Node* pRoot)
{
if (NULL == pRoot)
return;
swap(pRoot->_pLeft, pRoot->_pRight);
_BinaryMirror(pRoot->_pLeft);
_BinaryMirror(pRoot->_pRight);
}
//二叉树的镜像—非递归
void _BinaryMirror_Nor()
{
if (NULL == _pRoot)
return;
queue<Node*>q;
q.push(_pRoot);
while (!q.empty())
{
Node*pCur = q.front();
if (pCur)
{
q.push(pCur->_pLeft);
}
if (pCur)
{
q.push(pCur->_pRight);
}
if (NULL!=pCur)//必须判断
swap(pCur->_pLeft, pCur->_pRight);
q.pop();
}
}
private:
Node* _pRoot; // 指向树的根节点
};
二叉树常见的面试题(1)
二叉树的实现与操作
最新推荐文章于 2025-01-23 21:29:32 发布
本文介绍了一种通用的二叉树数据结构实现方法,包括递归与非递归方式下的遍历算法,如前序、中序、后序及层序遍历等,并详细解释了二叉树的创建、查找、镜像翻转等功能。
1154

被折叠的 条评论
为什么被折叠?



