数据结构---二叉树
1、二叉树结构
class Node{ int value; Node left; Node right; Node(int data){ this.value=data; } }
2、二叉树遍历
前序遍历--递归方式
public void preOrderRecur(Node head){ if(head==null) return; System.out.println(head.value+" "); preOrderRecur(head.left); preOrderRecur(head.right); }
非递归方式:申请一个栈,先把头结点压入栈中,然后弹出,再把该节点的右子树压入栈中,再把左子树压入栈中,依次循环上述操作。
public static void preOrderRecur(Node head){ Stack stack= new Stack(); if(head==null) return; stack.push(head); Node node; while(!stack.isEmpty()){ node=(Node) stack.pop(); System.out.println(node.value); if(node.right != null) stack.push(node.right); if(node.left != null) stack.push(node.left); } }
中序遍历--递归方式
非递归方式:public void inOrderRecur(Node head){ <span style="white-space:pre"> </span>if(head==null) return; <span style="white-space:pre"> </span>inOrderRecur1(head.left); <span style="white-space:pre"> </span>System.out.println(head.value); <span style="white-space:pre"> </span>inOrderRecur1(head.right); <span style="white-space:pre"> </span>}
1、申请一个栈,记为stack,申请一个变量为curr,初始时令cur等于头结点
2、先把cur压入栈中,对以cur节点为头结点的整棵子树来说,依次把整棵树的左边界压入栈中,即不断令cur=cur.left,然后重复步骤2
3、不断重复步骤2,直到发现cur为空,此时从stack中弹出一个节点,记为node,打印node的值,并让cur=node.right,将其压入栈中,继续重复步骤2
4、当stack为空并且cur为空时,整个过程结束。
public static void inOrderRecur(Node head){ Stack<Node> stack =new Stack<Node>(); if(head==null) return; Node curr = head; stack.push(curr); while (!stack.isEmpty()|| curr !=null) { while(curr.left!=null){ stack.push(curr.left); curr=curr.left; } if(!stack.isEmpty()){ Node node=stack.pop(); System.out.println(node.value); if(node.right !=null){ curr = node.right; stack.push(curr); } } } }
后序遍历--递归方式
public void afterOrderRecur1(Node head){ if(head==null) return; <span style="font-family: Arial, Helvetica, sans-serif;">afterOrderRecur1</span><span style="font-family: Arial, Helvetica, sans-serif;">(head.left);</span> <span style="font-family: Arial, Helvetica, sans-serif;">afterOrderRecur1</span><span style="font-family: Arial, Helvetica, sans-serif;">(head.right);</span> System.out.println(head.value+" "); }
非递归形式:申请两个栈
1、申请一个栈记为S1,将数的头结点压入到S1中
2、从S1中弹出一个节点记为cur,然后将其右子节点压入到S1中,再将其左子树节点压入到S1中
3、在整个过程中,从S1中弹出的节点均放入到S2中
4、不断重复步骤2和步骤三
5、从S2中依次弹出并打印。
public static void afterOrderRecur(Node head){ if(head==null) return; Stack<Node> s1= new Stack<Node>(); Stack<Node> s2= new Stack<Node>(); s1.push(head); while(!s1.isEmpty()){ Node cur=s1.pop(); s2.push(cur); if(cur.left!=null)s1.push(cur.left); if(cur.right!=null)s1.push(cur.right); } while(!s2.isEmpty()){ System.out.println(s2.pop().value); } }
不管是递归方式还是非递归方法,遍历整棵树的时间复杂度都是O(N),N为二叉树的节点树,额外空间复杂度为O(L),L为二叉树的层数
判断平衡二叉树:通过后序遍历来实现,首先判断左子树是不是平衡二叉树,再判断右子树是不是平衡二叉树
public static boolean isBalance(Node head){ boolean[] res = new boolean[1]; res[0]=true; getHeight(head,1,res); return res[0]; } private static int getHeight(Node head, int level,boolean[] res) { if(head==null){ return level; } int lH = getHeight(head.left,level + 1,res); if(!res[0]){ return level; } int rH=getHeight(head.right, level+1, res); if(!res[0]){ return level; } if(Math.abs(lH-rH)>1){ res[0]=false; } return Math.max(lH,rH); }
搜索二叉树 :每棵树的头结点都比各自左子树上的所有节点值要大,也都比各自右子树上的所有节点值要小。按中序遍历得到的顺序是从小到大的。
判断是否是搜索二叉树:
满二叉树:除了最后一层的节点无任何子节点外,剩下每一层上的节点都有两个子节点。 满二叉树的层数为L,节点数为N,则N=2^L-1
完全二叉树:除最后一层外,其他每一层的节点数都是满的。最后一层如果不满,缺少的节点也全部的集中在右边,那也是一颗完全二叉树。
后继节点:一个节点的后继节点,是指这个节点在中序遍历中的下一个节点判断完全二叉树:
1、采用按层遍历二叉树的方式,从每层的左边向右边依次遍历所有的节点
2、如果当前节点有右孩子,但没有左孩子,直接返回false
3、如果当前节点并不是左右孩子全有,那之后的节点必须都为叶子节点,否则返回false
4、遍历过程中不反回false,遍历结束后返回true即可
前驱节点:这个节点在中序遍历中的上一个节点。