以前上数据结构的时候看着老师敲,并没有亲自去把整个实现和相关操作都实现,只记得一些。导致在进行剑指offer练习的时候层次遍历不太清楚,只了解先序遍历、中序遍历和后序遍历的操作流程。然后也吐槽一下,牛客网这题的测试用例不够,导致一些错误代码也能通过。具体通过的是什么样的代码,后续另一起篇说明一下。关于注释部分代码是对上面提到那题的二叉树的构造。
为什么会突然想写关于二叉树呢? 是因为遇到了另一题二叉树的生成方式跟注释有点不一样,而那题我本人看错题,看成了权值最大的节点到权值最小的节点的路径,实际上是叶节点。然后在讨论区看到一个大佬写的代码,仔细分析了一下。发现是先序遍历的做法,为了确认分析没错,就把代码copy到本地,为了测试,编写了关于此完全二叉树的构造,顺带回顾知识加深理解。
概念
在计算机科学中,二叉树是每个结点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。
一棵深度为k,且有2^k-1个结点的二叉树,称为满二叉树。这种树的特点是每一层上的结点数都是最大结点数。而在一棵二叉树中,除最后一层外,若其余层都是满的,并且或者最后一层是满的,或者是在右边缺少连续若干结点,则此二叉树为完全二叉树。具有n个结点的完全二叉树的深度为floor(log2n)+1。深度为k的完全二叉树,至少有2k-1个叶子结点,至多有2k-1个结点。
与普通树不同,普通树的节点个数至少为1,而二叉树的节点个数可以为0;普通树节点的最大分支度没有限制,而二叉树节点的最大分支度为2;普通树的节点无左、右次序之分,而二叉树的节点有左、右次序之分。
二叉树通常作为数据结构应用,典型用法是对节点定义一个标记函数,将一些值与每个节点相关系。这样标记的二叉树就可以实现二叉搜索树和二叉堆,并应用于高效率的搜索和排序。
来源:维基百科 百度百科
完全二叉树
定义: 若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。
完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。
(1)所有的叶结点都出现在第k层或k-l层(层次最大的两层)
(2)对任一结点,如果其右子树的最大层次为L,则其左子树的最大层次为L或L+l。
一棵二叉树至多只有最下面的两层上的结点的度数可以小于2,并且最下层上的结点都集中在该层最左边的若干位置上,则此二叉树成为完全二叉树,并且最下层上的结点都集中在该层最左边的若干位置上,而在最后一层上,右边的若干结点缺失的二叉树,则此二叉树成为完全二叉树。
完全二叉树代码实现
根据完全二叉树的定义,利用层次遍历的方法去构造,并将构造的二叉树打印出来。
而判断是否为完全二叉树,可以利用层次遍历去判断。
public class TreeNode {
private int val;
private TreeNode left;
private TreeNode right;
private LinkedList<TreeNode> queue = new LinkedList<>();
public TreeNode(int val) {
this.val = val;
if (queue.size() == 0) {
queue.add(this);
}
}
public void add(int val) {
// 如果val < 父亲结点的值则放入左孩子
/*if (val < this.val) {
if (this.left == null) {
this.left = new TreeNode(val);
}else {
this.right.add(val);
}
}else {
if (this.right == null) {
this.right = new TreeNode(val);
}else {
this.left.add(val);
}
}*/
TreeNode temp;
while (queue.size() != 0) {
temp = queue.peek();
if (temp.left == null) {
temp.left = new TreeNode(val);
break;
}
if (temp.right == null) {
temp.right = new TreeNode(val);
queue.add(temp.left);
queue.add(temp.right);
queue.remove();
break;
}
queue.remove();
}
}
public void printTree(TreeNode root) {
if (root == null) {
return;
}
printTree(root.left);
System.out.print(root.val + "->");
printTree(root.right);
}
}