二叉树
二叉树概念
二叉树:每个节点最多有两个子节点
满二叉树:深度为K,有2^k-1个节点
完全二叉树:满二叉树属于完全二叉树,最后一层可满可不满,不满只可右部分缺失,其余层是满的
平衡二叉树:一棵空树或者左右子树的高度差的绝对值不能超过1
二分查找树:左子树节点的值比该节点的值小,右子树节点的值比该节点的值大
前序遍历
首先访问根节点,然后遍历其左节点,再遍历其右节点
实现方式 1:递归,先访问根节点,然后分别递归调用左子树和右子树
public void preOrder(TreeNode treeNode){ if(treeNode==null){ return; } System.out.print(treeNode.getValue()); preOrder(treeNode.getLeft()); preOrder(treeNode.getRight()); }
实现方式 2:迭代,本质上就是模拟递归实现栈的存储过程。沿着左子树向下访问到叶子节点;从栈中取出栈顶元素,向右转弯,执行第一步逻辑
private void preOrderIteration(TreeNode treeNode){ if(treeNode==null){ return; } Stack<TreeNode> treeNodeStack=new Stack<>(); while (treeNode!=null){ while (treeNode!=null){ System.out.println(treeNode.getValue()); treeNodeStack.push(treeNode); treeNode=treeNode.getLeft(); } while (!treeNodeStack.empty() && treeNode==null){ treeNode=treeNodeStack.pop(); treeNode=treeNode.getRight(); } } }
中序遍历
实现方式 1:递归,首先遍历左子树、然后访问根节点,最后遍历右子树
private void inOrder(TreeNode treeNode){ if(treeNode==null){ return; } inOrder(treeNode.getLeft()); System.out.print(treeNode.getValue()); inOrder(treeNode.getRight()); }
实现方式 2:迭代,与前序遍历相似,只是访问节点时机不同。沿着左子树向下访问到根节点,访问栈顶元素,向右转弯,执行第一步逻辑
private void inOrderIteration(TreeNode treeNode){ if(treeNode==null){ return; } Stack<TreeNode> treeNodeStack=new Stack<>(); while (treeNode!=null){ while (treeNode!=null){ treeNodeStack.push(treeNode); treeNode=treeNode.getLeft(); } while (!treeNodeStack.empty() && treeNode==null){ treeNode=treeNodeStack.pop(); System.out.println(treeNode.getValue()); treeNode=treeNode.getRight(); } } }
后序遍历
实现方式 1:递归,首先遍历左子树、然后遍历右子树,最后访问根结点。
private void afterOrder(TreeNode treeNode){ if(treeNode==null){ return; } afterOrder(treeNode.getLeft()); afterOrder(treeNode.getRight()); System.out.print(treeNode.getValue()); }
实现方式 2:迭代,后序遍历的迭代实现又分为单栈实现和双栈实现
单栈实现:沿着左子树向下访问到叶子节点。栈顶元素出栈,判断是否存在右子树:若存在,当前节点重复入栈,并且其right引用置null,以免下次出栈再次遍历其右子树;若不存在,访问当前节点。右转弯到右子树上,回到第1步或2步。
private void postOrderIteration(TreeNode treeNode){ if(treeNode==null){ return; } Stack<TreeNode> treeNodeStack=new Stack<>(); while (treeNode!=null){ while (treeNode!=null){ treeNodeStack.push(treeNode); treeNode=treeNode.getLeft(); } while (!treeNodeStack.empty() && treeNode==null){ treeNode = treeNodeStack.pop(); TreeNode rightNode=treeNode.getRight(); if(rightNode==null){ System.out.print(treeNode.getValue()); }else { treeNodeStack.push(treeNode); treeNode.setRight(null); } treeNode=rightNode; } } }
双栈实现:stack1用于规划下一个将要访问的节点,stack2保存后序遍历节点访问的顺序
private void postOrderIteration2(TreeNode treeNode){ if(treeNode==null){ return; } Stack<TreeNode> stack1=new Stack<>(); Stack<TreeNode> stack2=new Stack<>(); stack1.push(treeNode); while (!stack1.empty()){ //下一个访问的节点 treeNode= stack1.pop(); stack2.push(treeNode); //先入栈左子树节点 if(treeNode.getLeft()!=null){ stack1.push(treeNode.getLeft()); } //再入栈右子树节点,这样下一个访问的将是右子树 if(treeNode.getRight()!=null){ stack1.push(treeNode.getRight()); } } //stack2元素出栈顺序即是后序遍历顺序 while (!stack2.empty()){ System.out.print(stack2.pop().getValue()); } }
分层遍历
private void floorOrder(TreeNode treeNode){ if(treeNode==null){ return; } LinkedList<TreeNode> linkedList=new LinkedList<>(); linkedList.add(treeNode); TreeNode currectNode; while (linkedList!=null && linkedList.size()>0){ currectNode=linkedList.poll(); if(currectNode!=null){ System.out.print(currectNode.getValue()); linkedList.add(currectNode.getLeft()); linkedList.add(currectNode.getRight()); } } }