Class Node{ V value; Node left; Node right; }
递归序
二叉树 先序 中序 后序遍历
// 先序打印所有节点
public static void pre(Node head){ if(head ==null){ return; } System.out.println(head.value); pre(head.left); pre(head.right); }
迭代实现 头节点 左节点 右节点
非递归(栈实现)
栈是先进后出 所以优先处理 左孩子
public static void pre(Node head){ System.out.print("pre-order"); if(head != null){ Stack<Node> stack = new Stack<Node>(); stack.add(head); while(!stack.isEmpty()){ head=stack.pop(); System.out.print(head.value +" "); if(head.right !=null){ stack.push(head.right); } if(head.lfet != null){ stack.push(head.left); } } } System.out.println(); }
中序遍历 先 左 头 右
public static void in(Node head){ System.out.print("in- order: ""); if(head != null){ Stack<Node> stack = new Stack<Node>(); while(! stack .isEmpty() || head!= null){ // 保证节点不为空 if(head != null){ stack.push(head); head=head.left; }else { // 一直到左最子树的最左节点 head= stack.pop(); System.out.print(head.value+ " "); head = head.right; } } } System.out.println(); } public static void in(Node head){ if(head == null){ return ; } in(head.left); System.out.printfln(head.value); in(head.right); }
后序打印
迭代实现 头节点 右节点 左节点
非递归(栈实现)
栈是后见先出 所以优先处理 右孩子 其逆序实现了 后序
在头右左 这个栈中 在打印的时候 不进行打印 重新压入一个栈
结束后 在进行打印
public static void pos1(Node head){ System.out.print("pos-order: "); if(head !=null){ Stack<Node> s1 = new Stack<Node>(); Stack<Node> s2 = new Stack<Node>(); s1.push(head); while(s1.isEmpty()){ head = s1.pop(); s2.push(head); if(head.left != null){ s1.push(head.lfet); } if(head.right !=null){ s2.push(head.right); } } while(s2.isEmpty()){ System.out.print(s2.pop().value+" "); } } System.out.println(); }
一个栈 实现后序遍历
h的变化 c的变化 栈的变化
public static void pos(Node h){ System.out.print("pos-order: "); if(h != null){ Stack<Node> stack = new Stack<Node>(); stack.push(h); Node c=null; while(! stack.isEmpty()){ c = stack .peek(); if(c.left != null && h != c.left && h != c.right){ stack.push(c.left); } esle if(c.right != null && h != c.right){ stack.push(c.right); } else { System.out.print(stack.pop().value+' '); // 打印栈栈顶的节点 // 用 h 进行标记当前树中左子树一或者右子树是否访问过 h=c; // h在跟踪上次打印的数字 } } } System.out.println(); }
二叉树的宽度遍历 (层序遍历) 用队列
public static void lavel(Node head){ if(head == null){ return ; } Queue <Node> queue = new LinkedList(); while(! queue .isEmpty()){ Node cur =queue.poll; System.out.print(cur.value){ if(cur.left != value) queue.add(cur.left); if(cur.right != null){ queue.add(cur.right); } } } }
要求要按层打印 而且还要判断出每一层的最大宽度 每层最有多少个节点
(可以判断出一层的开始 或者一层的结束)
public class TreeMaxWidth{ public static class Node{ public int value; public Node left; public Node right; public Node(int data){ this.value=data; } } public static maxWidthUseMap(Node head){ if(head == null){ return 0; } Queue<Node> queue = new LinkedList<>(); queue.add(head); // key 在那一层 value HashMap<Node , Integer> levelMap = new HashMapM<>(); levelMap.put(head,1); int curLevel=1; // 当前正在统计那一层的宽度 int curLevelNodes=0; // 当前层的宽度 int max=0; // 整颗树 目前为止 最大宽度 while(! queue.isEmpty()){ Node cur = queue.poll(); int curNodeLevel = levelMap.get(cur); // 当前节点的层数 if(cur.left ! = null){ levelMap.put(cur.left , curNodeLevel+1); // 标记当前节点的左孩子 以及层数 queue.add(cur.lfet); } if(cur.right ! = null){ levelMap.put(cur.right, curNodeLevel+1); queue.add(cur.right); } if(curNodeLevel == curLevel){ curLevelNodes++; }else{ max=Math.max(max,curLevelNodes); curLevel++; //更新当前层 curLevelNodes =1; // 此处当新层弹出的第一个节点 所以加加 } } max= Math.max(max, curLevelNdoes); //需要在更新一次,最后一次没有新的层 去更新和结算max return max; } }
public static maxWidthNoMap(Node head){ if(head == null) return 0; Queue<Node> queue = new LinkedList<>(); queue.add(head); Node curEnd = head; // 当前层最后一个节点(当前层的最右边的节点) Node nnextEnd = null; // 下一层最右边节点 int max=0; int curLevelNodes = 0; // 当前层的节点数 while(! queue.isEmpty()){ Node cur = queue.poll(); if(cur.lfet != null){ queue.add(cur.left); nextEnd=cur.left; } if(cur.right ! =null){ queue.add(cur.right); nextEnd = cur.right; } curLevelNodes++; if(cur == curEnd){ // 判断当前 节点是否是本层的最右边节点 max = Math.max(max, curLeveNOdes); curLevelNodes =0; curEnd = nextEnd; } } }
二叉树的序列化 和 反序列
(将树 线性的保存起来) 通过字符串 或者 数组 可以彻底还原成为一个树
在数组中记录这个数组的所有节点 包括空节点
序列化和结构 一一对应
public static class Node { // 树的结构 建立 public int value; public Node left; public Node right; public Node(int data){ this.value =data; } } public static Queue <String> PreSerial(Node head){ Queue<String> ans = new LinkedList<>(); pres(head,ans); return ans; } // 先序 序列化 将节点存入队列中 public static void pres(Node head, Queue<String> ans){ if(head == null){ // 空节点也加入 ans.add(null); }else { ans.add(String.valueOf(head.value)); // 将节点 变成字符串 放入队列中 pres(head.left, ans); pres(head.right, ans); } } public static Node buildByPreQueue (Queue<String> prelist){ if( prelist == null || prelist.size() ==0){ return null; } return preb(prelist); // 先序 方式 利用队列 建立 正棵树 } public static preb(Queue<String> prelist){ String value = prelist.poll(); if(value == null) return null; Node head = new Node(Integer.valueOf(value)); // 转换为整型 head.left = preb(prelist); head.right=preb(prelist); return head; }