是否完全二叉搜索树
题干
测试样例 1
输入样例
9
38 45 42 24 58 30 67 12 51
输出样例
38 45 24 58 42 30 12 67 51
YES
测试样例 2
输入样例
8
38 24 12 45 58 67 42 51
输出样例
38 45 24 58 42 12 67 51
NO
题目分析
这道题目可以被分为 2 部分,分别是建立二叉搜索树和判断是否是完全二叉树。首先是建立二叉搜索树,这个操作并不难,只需要使用上文给出的建树函数,循环调用插入函数就行。值得注意的是这道题左子树是较大的关键字,右子树是较小的关键字。
接下来就是判断是否是完全二叉树,首先我们先回忆一下什么是完全二叉树。我使用通俗的话来说,所谓完全二叉树就是生成结点的顺序是严格按照从上到下,从左往右的顺序来构建的二叉树。例如对于题设测试样例 1 所建立的二叉搜索树,我把它展开为拓展二叉树的形式:
若按照“从上到下,从左到右”的顺序去读这个二叉树,会发现空结点只会集中出现在末尾部分。下面再看测试样例 2:
从定义上讲,这不是个完全二叉树,若展开成拓展二叉树的形式,按照“从上到下,从左到右”的顺序去读这个二叉树,会发现有个空结点穿插在了结点之间。
也就是说要判断一个二叉树是否是完全二叉树,可以先展开为拓展二叉树,然后按照“从上到下,从左到右”的顺序遍历这个二叉树,若在所有实际存在的结点遍历完毕之前遇到了空结点,就说明这不是完全二叉树。如何实现“从上到下,从左到右”的顺序遍历?这就是所谓的层序遍历法,需要通过一个队列结构来辅助实现。对于二叉树的相关概念和操作,可以前往博客——二叉树结构详解进行回顾。
总体的思路已经很明确了,接下来就是如何体现中间遇到了空结点?在层序遍历中我们可以直接忽略空结点,不让空结点入队列,但是这里必须用拓展二叉树的思想让空结点入队列,这样我们才能确定是否有空结点的出现。但是如果是这样的话,可以在空结点入队列时判断不是完全二叉树吗?也不行,因为这么操作在最后会有一系列空结点入队列。