三.判断二叉树是否为完全二叉树:
我们先来看看这张图:
我们会发现,通过层序遍历的方法,满二叉树在层序遍历时的非空结点一定是连续的,空结点也是连续的,所以我们只要在层序遍历的基础上把空结点存入,然后判断空结点是否连续即可。
代码实现:
// 判断二叉树是否是完全二叉树 bool TreeComplete(BTNode* root) { Queue q; QueueInit(&q); if (root) QueuePush(&q, root); while (!QueueEmpty(&q)) { BTNode* front = QueueFront(&q); QueuePop(&q); if (front == NULL) { break; } else { QueuePush(&q, front->left); QueuePush(&q, front->right); } } // 判断是不是完全二叉树 while (!QueueEmpty(&q)) { BTNode* front = QueueFront(&q); QueuePop(&q); // 后面有非空,说明非空节点不是完全连续 if (front) { QueueDestroy(&q); return false; } }
四.二叉树结点数量:
如果我们要计算结点的数量,通过上面所学的遍历的方式当然可以计算出结点数量。
这就是遍历的方法,但是事实上我们用分治的方法更多一些:
分治和遍历的区别:
拿学校人口统计作为例子,遍历法与分治法的区别如下:
遍历法,做法如下:
校长自己一个人带着一个本子,跑遍全校查人数
分治法,做法如下:
校长想知道人数,就找来院长统计每个院的人数相加,院长找来系主任统计每个系的人数相加……这样校长就不用亲自动手了。其实递归就是把任务交给打工人(呜呜)。
那么我们如何实现分治法呢?
总体思路就是 返回:左子树数量+右子树数量+1
代码实现:
int TreeSize(BTNode* root) { return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1; }
五.二叉树的高度(深度):
在这里要求二叉树的高度,我们也是用分治的思想:
int TreeHeight(BTNode* root) { if (root == NULL) { return 0; } int leftHeight = TreeHeight(root->left); int rightHeight = TreeHeight(root->right); return leftHeight > rightHeight ? leftHeight+1 : rightHeight+1; }
其实对于递归内容,我们只需要考虑:
将问题分为子问题,子问题的解决方式和总问题的解决方式的方式一样
有中止的条件
六.二叉树第k层节点个数
现在我们把他分为子问题:
当前树的第k层个数=左子树的第k-1层个数+右子树的第k-1层个数
代码如下:
int TreeKLevel(BTNode* root, int k) { if (root == NULL) { return 0; } if (k == 1) { return 1; } int leftklevel = TreeKLevel(root->left, k - 1); int rightklevel = TreeKLevel(root->right, k - 1); return leftklevel + rightklevel; }