二叉树是很基本的但是又很重要的数据结构。
何为二叉树?
struct BinaryTreeNode
{
int m_Value;
BinaryTreeNode* m_Left;
BinaryTreeNode* m_Right;
}
每个节点有一个值和最多两个孩子节点,有左右孩子之分。
其中,没有孩子节点的节点称为叶子节点。
具体列表如下:
1.求节点个数
2.求树的深度
3.前序遍历 中序遍历 后序遍历
4.分层遍历
5.将二叉树变为有序的双向列表
6.求第n层的节点个数
7.求叶子节点的个数
8.判断两棵二叉树是否结构相同
9.判断是否为平衡二叉树
10.求二叉树的镜像
11.求二叉树的两个节点的最低公共祖先节点
12.求两个节点的最大距离
13.由前序遍历序列和中序遍历序列重建二叉树
14.判断是否为完全二叉树
通常与二叉树有关的问题都可以用递归思想解决。
具体思路及实现代码如下:
1.求节点个数
(1) 如果节点为空,则节点个数为0;
(2)如果节点不为空,则
二叉树结点个数 = 左孩子节点个数 + 右孩子节点个数 + 1
代码如下:
int GetNodeNum(BinaryTreeNode* Root)
{
if(Root == NULL)
{
return 0;
}
else
{
return GetNodeNum(Root->m_Left)
+ GetNodeNum(Root-> m_Right) + 1;
}
}
2.求树的深度
(1) 如果节点为空,则二叉树的深度为0;
(2)如果节点不为空,则
二叉树的深度 = max(左孩子深度,右孩子深度) + 1
代码如下:
int GetDepth(BinaryTreeNode* Root)
{
if(Root == NULL)
{
return 0;
}
else
{
int DepthLeft ;
DepthLeft= GetDepth(Root->m_Left);
int DepthRight;
DepthRight = GetDepth(Root->m_Right);
return DepthLeft>DepthRight?(DepthLeft+1):(DepthRight+1);
}
}
3.前序遍历 中序遍历 后序遍历
前序遍历
(1) 如果节点为空,不进行操作;
(2)如果节点不为空,则访问节点,前序遍历左孩子,
前序遍历右孩子;
代码如下:
void PreOrder(BinaryTreeNode* Root)
{
if(Root == NULL)
{
return;
}
Visit(Root); // 访问节点
PreOrder(pRoot->m_Left);
// 前序遍历左子树
PreOrder(pRoot->m_Right);
// 前序遍历右子树
}
中序遍历
(1) 如果节点为空,不进行操作;
(2)如果节点不为空,中序遍历左孩子,则访问节点,
中序遍历右孩子;
代码如下:
void InOrder(BinaryTreeNode* Root)
{
if(Root == NULL)
{
return;
}
InOrder(Root->m_Left);
// 中序遍历左子树
Visit(Root);
// 访问节点
InOrder(Root->m_Right);
// 中序遍历右子树
}
后序遍历
(1) 如果节点为空,不进行操作;
(2)如果节点不为空,后序遍历左孩子, 后序遍历右孩子,
则访问节点;
代码如下:
void PostOrder(BinaryTreeNode* Root)
{
if(Root == NULL)
{
return;
}
InOrder(Root->m_Left);
// 后序遍历左子树
InOrder(Root->m_Right);
// 后序遍历右子树
Visit(Root);
// 访问节点
}
4.分层遍历 (从上往下,从左至右)
相当于广度优先搜索,使用队列实现。
队列初始化,将根节点压入队列。
当队列不为空,进行如下操作:弹出一个节点,访问,若左子节点或右子节点不为空,将其压入队列。
代码如下
void Level(BinaryTreeNode* Root)
{
if(Root == NULL)
{
return;
}
queue<BinaryTreeNode *> q;
q.push(Root);
while(!q.empty())
{
BinaryTreeNode * pNode = q.front();
q.pop();
Visit(pNode); // 访问节点
if(pNode->m_Left != NULL)
{
q.push(pNode->m_Left);
}
if(pNode->m_Right != NULL)
{
q.push(pNode->m_Right);
}
}
return;
}
6.求第n层的节点个数
(1)如果二叉树为空或者k<1返回0(2)如果二叉树不为空并且k==1,返回1
(3)如果二叉树不为空且k>1,返回左子树中k-1层的节点个数与右子树k-1层节点个数之和
代码如下:
int GetLevelNum(BinaryTreeNode * Root, int n)
{
if(pRoot == NULL || n < 1)
{
return 0;
}
else
{
if(k == 1)
{
return 1;
}
int numLeft = GetLevelNum(Root->m_Left, n-1);
// 左子树中k-1层的节点个数
int numRight = GetLevelNum(Root->m_Right, k-1);
// 右子树中k-1层的节点个数
return (numLeft + numRight);
}
}
int GetLevelNum(BinaryTreeNode * Root, int n) { if(pRoot == NULL || n < 1) { return 0; } else { if(k == 1) { return 1; }int numLeft = GetLevelNum(Root->m_Left, n-1); // 左子树中k-1层的节点个数int numRight = GetLevelNum(Root->m_Right, k-1); // 右子树中k-1层的节点个数 return (numLeft + numRight);}}
6. 求二叉树第K层的节点个数
(1)如果二叉树为空,返回0
(2)如果二叉树不为空且左右子树为空,返回1
(3)如果二叉树不为空,且左右子树不同时为空,返回左子树中叶子节点个数加上右子树中叶子节点个数
参考代码如下:
int GetLeafNum(BinaryTreeNode * Root)
{
if(Root == NULL)
{
return 0;
}
if(Root->m_Left == NULL && Root->m_Right == NULL)
{
return 1;
}
int numLeft = GetLeafNum(Root->m_Left);
// 左子树中叶节点的个数
int numRight = GetLeafNum(Root->m_Right);
// 右子树中叶节点的个数
return (numLeft + numRight);
}
不考虑数据内容。结构相同意味着对应的左子树和对应的右子树都结构相同。
递归解法:
(1)如果两棵二叉树都为空,返回真
(2)如果两棵二叉树一棵为空,另一棵不为空,返回假
(3)如果两棵二叉树都不为空,如果对应的左子树和右子树都同构返回真,其他返回假
代码如下: