【算法】后序遍历判断二叉树是否为平衡二叉树

10 篇文章 1 订阅
6 篇文章 0 订阅

1. 前言

  • 来自广工考研真题
  • 平衡二叉树是一种高级数据结构,是O(nlogn)搜索算法的基础数据结构
  • 拆解题目内容: 后序遍历求树高度 + 全局计数器 + 节点平衡定义 + 返回值语义确认
  • 实现方式:递归遍历 + 引用类型做全局计数器

2. 读题

  • “判断” 属于二叉树的遍历
  • “是否” 则是遍历中需要做的具体操作
  • “平衡” 来自于定义:任意节点左右子树高度差小于2 => |左子树高度 - 右子树高度| < 2

3. 梳理思路

递归得让每个节点知道自己所在的高度,并向上报告,其双亲节点判断自己的左右子树是否平衡。任意子树不平衡,整棵树都不平衡。

  • 为什么使用递归?
    总问题可以分割成相同的子问题,子问题依次解决后总问题解决。契合递归的思想。

  • 为什么使用后序遍历?
    后续遍历是最后访问根节点,从叶子节点慢慢回溯到根节点,每个双亲节点都能知道左右孩子的信息。

  • 为什么使用全局计数器?
    树的高度 在递归回溯的过程中是单项递增的,如果方法签名定义一个引用类型&int i,递归结束即可为i赋值为整棵树的高度。

  • 如何确定返回值?
    “任意子树不平衡,整棵树都不平衡。”,返回值使用布尔类型
    返回值一方面也是为了简化递归过程,也就是剪枝的功能,剪枝 是个大话题,这里不表。
    换言之,已经存在任意子树不平衡了,直接向上返回FALSE 就好,如下代码能做到的就是,左边子树出现了不平衡,后续省略右子树的判断。函数输出TRUE 则为平衡二叉树

    if ( ! f(T -> lchild) || ! f(T -> rchild) ) {
      return false;
    }
    

4. 实现

4.1 结构体定义

typedef struct BiTNode {
	int data;
	struct BitNode *lchild, *rchild;
} BiTNode, *BiTree;

4.2 使用引用类型记录高度,返回值作为剪枝依据(不可运行)

bool f(BiTree T, int &h) {
	if (NULL == T) { // 1. 空子树, 高度为0, 一定平衡。 
		h = 0;
		return TRUE;
	}
	int h1, h2; // 左右子树高度
	if(T->lchild == NULL && T->rchild == NULL) {
		h = 1;
		return TRUE; // 2. 递归到叶子节点的空节点,高度为1,一定平衡。
	}
	if ( ! f(T->lchild, h1) ||  ! f(T->rchild, h2) ) {
	    //  递归出口,任意子树不平衡整个树不平衡,h这里对于算法无意义了,可以不赋值
		return FALSE;
	}
}

4.3 后序遍历求树的高度

可以作为独立的代码实现,也可以作为4.4 的编码依据

int f(BiTree T) {
	if (T == null) return 0;
	int leftHight = f(T->lchild);
	int rightHight = f(T -> rchild);
	return 1 + (leftHight > rightHight ? leftHight : rightHight ); // 双亲节点的高度 = 左右子树高度最大值 + 1
}

4.4 加入判断是否平横的逻辑完整代码 (可运行)

bool f(BiTree T, int &h) {
	if (NULL == T) { // 1. 空子树, 高度为0, 一定平衡。 
		h = 0;
		return TRUE;
	}
	int h1, h2; // 左右子树高度
	if(T->lchild == NULL && T->rchild == NULL) {
		h = 1;
		return TRUE; // 2. 递归到叶子节点的空节点,高度为1,一定平衡。
	}
	if ( ! f(T->lchild, h1) ||  ! f(T-> rchild, h2) ) {
	    // 递归出口,任意子树不平衡整个树不平衡,h这里对于算法无意义了,可以不赋值
		return FALSE;
	}
	
	// 记录回溯到该双亲节点时的高度
	h = 1 + (h1 > h2 ? h1 : h2);
	
	// 当前节点作为双亲节点,根据左右节点高度判断是否不平衡。 abs() 取绝对值
	return (abs(h1 - h2)) < 2;  
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值