数据结构之二叉树的基本操作

二叉树是很基本的但是又很重要的数据结构。

何为二叉树?

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)如果两棵二叉树都不为空,如果对应的左子树和右子树都同构返回真,其他返回假
代码如下:
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值