思路
完全二叉樹和非完全二叉樹的最大的區別就是完全二叉樹的葉子節點只能在最后一層后者倒數第二層,其他層其實是一個滿二叉樹,而且最后一層的葉子節點都要靠近最左邊。
如圖:
二叉樹的構成代碼和節點代碼
二叉樹:

package com.example.demo.tree; import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer; import org.omg.PortableInterceptor.INACTIVE; import java.util.Comparator; /** * @author steve * @date 2020/4/16 10:03 上午 */ public class BinaryTree<E> { private int size; public Node<E> root; private Comparator<E> comparator; public BinaryTree(Comparator<E> comparator){ this.comparator = comparator; } public BinaryTree(){ this(null); } public void add(E element){ if (root == null){ Node node = new Node(element); root = node; }else { Node<E> parent = root; Node<E> node = root; int com = 0; while (node != null){ parent = node; if (comparator == null){ com = ((Comparable)node.element).compareTo(element); }else { System.out.println("-------------"); com = comparator.compare(node.element,element); } if (com > 0){ node = node.left; }else if (com < 0){ node = node.right; }else { node.element = element; return; } } Node<E> newNode = new Node(element); if (com > 0){ parent.left = newNode; newNode.parent = parent.left; }else{ parent.right = newNode; newNode.parent = parent.right; } } size ++; } public boolean isEmpty(){ return size == 0; } public int size(){ return size; } public String toString() { String d = root == null ? null : root.element + ""; if (root == null){ return "root:"+d; }else { String b = root.left == null ? null : root.left.element + ""; String c = root.right == null ? null : root.right.element + ""; return "root:"+d + ", left:" + b + ", right:"+ c; } } public static void main(String[] args) { //這種方式就是匿名內部類,通過給一個類傳一個接口作為參數,然后這個通過一個匿名內部類是實現這個接口來傳入實現。 BinaryTree<Integer> binaryTree = new BinaryTree<>(new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o1 - o2; } }); BinaryTree<Integer> binaryTree1 = new BinaryTree<>(); binaryTree1.add(1); binaryTree1.add(2); binaryTree1.add(0); System.out.println(binaryTree1.size()); System.out.println(binaryTree.toString()); } }
節點:

package com.example.demo.tree; /** * @author steve * @date 2020/4/18 3:16 下午 */ public class Node<E> { public Node<E> left; public Node<E> right; public Node<E> parent; public E element; public Node(E element){ this.element = element; } }
判斷二叉樹是不是完全二叉樹
1 package com.example.demo.tree; 2 3 import java.util.LinkedList; 4 import java.util.Queue; 5 6 /** 7 * @author steve 8 * @date 2020/4/20 8:31 下午 9 * 判斷是不是完全二叉樹,采用層序遍歷的方式 10 * 判斷依據:如果某個節點沒有左子樹或者右子樹,就直接結束二叉樹遍歷,這時候隊列可能並不為空, 11 * 但是隊列中的節點必須都是葉子節點,否則就不是完全二叉樹 12 */ 13 public class JudgeFullBinaryTree { 14 15 public static void judge(Node<Integer> node){ 16 Queue<Node<Integer>> queue = new LinkedList<>(); 17 queue.add(node); 18 boolean flag = true; 19 while(!queue.isEmpty()){ 20 //這里沒有直接使用queue.poll()的原因是,如果最后那個節點沒有左子樹,但是有右子樹,那么這個循環也會停止, 21 //而且那個節點也會從隊列中彈出,如果剛好是那個節點就是問題節點,那最后的結果就是有問題的,所以這里使用peek 22 node = queue.peek(); 23 //遇見為空的直接停止 24 if (node.left != null){ 25 queue.add(node.left); 26 }else { 27 break; 28 } 29 //遇見為空直接停止 30 if (node.right != null){ 31 queue.add(node.right); 32 }else { 33 break; 34 } 35 queue.poll(); 36 } 37 //這里搞這個判斷的原因,就是看一下暫停遍歷的那個節點是不是有問題,因為上面的循環並沒有把這個節點彈出 38 if (queue.peek().right == null){ 39 queue.poll(); 40 } 41 //這里判斷隊列中剩余的節點是不是都是葉子節點 42 while (!queue.isEmpty()){ 43 node = queue.poll(); 44 if (node.left != null || node.right != null){ 45 flag = false; 46 } 47 } 48 System.out.println(flag); 49 } 50 51 /** 52 * 7 53 * / \ 54 * 4 10 55 * /\ /\ 56 * 3 5 9 11 57 * / 58 * 1 59 * / 60 * 0 61 * @param args 62 */ 63 public static void main(String[] args) { 64 BinaryTree<Integer> binaryTree = new BinaryTree(); 65 binaryTree.add(7); 66 binaryTree.add(4); 67 binaryTree.add(10); 68 binaryTree.add(9); 69 binaryTree.add(11); 70 binaryTree.add(5); 71 binaryTree.add(3); 72 binaryTree.add(1); 73 binaryTree.add(0); 74 judge(binaryTree.root); 75 } 76 77 }