先序思路:
先将头节点放入栈中,弹出打印,然后判断当前节点的右节点是否为空,不为空,放入栈中,然后再将当前节点的左节点放入栈中,因为放入的顺序是先右再左,利用了栈的特殊性,便实现了二叉树的非递归先序遍历
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list=new ArrayList<Integer>();
if(root==null){
return list;
}
preOrder(root,list);
return list;
}
public void preOrder(TreeNode root,List<Integer> list){
if(root==null){
return ;
}
Stack<TreeNode> stack=new Stack<TreeNode>();
stack.push(root);
while(!stack.isEmpty()){
TreeNode pop=stack.pop();
list.add(pop.val);
if(pop.right!=null){
stack.push(pop.right);
}
if(pop.left!=null){
stack.push(pop.left);
}
}
}
中序思路:
递归的实质就是调用栈的过程,不过调用过程不是我们来决定的,那我们就自己实现一个栈来进行遍历,
过程:head指针往下移动,一开始先将二叉树的所有左边界一次性放入栈中,然后直到head指针指向空,将栈中的元素打印,head指针移向打印的节点的右子节点,再进行判断是否有左边界,有全部放入栈中,若没有,则打印。循环此步骤。
//定义节点
public static class Node {
int val = 0;
Node left = null;
Node right = null;
public Node(int val) {
this.val = val;
}
}
public static void inOrder(Node head) {
if(head!=null) {
Stack<Node> stack=new Stack<Node>();
while(head!=null ||!stack.isEmpty()) {
if(head!=null) {
stack.push(head);
head=head.left;
}else {
head = stack.pop();
System.out.println(head.val);
head=head.right;
}
}
}
}
后序遍历
使用二个栈,一个先实现根右左,再利用另外一个栈实现反转得到左右根即二叉树的后序遍历
//后序遍历,非递归
public static List<Integer> postOrder2(TreeNode head) {
Stack<TreeNode> stack1=new Stack<TreeNode>();
Stack<TreeNode> stack2=new Stack<TreeNode>();
List<Integer> list=new ArrayList<Integer>();
stack1.add(head);
while(!stack1.isEmpty()) {
head = stack1.pop();
//System.out.println(head.val);
stack2.push(head);
if(head.left!=null) {
stack1.add(head.left);
}
if(head.right!=null) {
stack1.add(head.right);
}
}
while(!stack2.isEmpty()) {
list.add(stack2.pop().val);
}
return list;
}
层次遍历
思路:准备一个队列,一开始先将头节点放入队列,弹出打印,如果左节点不为空,将左节点放入,如果右节点不为空,放入右节点
public static void printByLevel(Node head) {
if(head==null) {
System.out.println(head);
}
Queue<Node> queue=new LinkedList<Node>();
queue.offer(head);
while(!queue.isEmpty()) {
head=queue.poll();
System.out.print(head.value+" ");
if(head.left!=null) {
queue.offer(head.left);
}
if(head.right!=null) {
queue.offer(head.right);
}
}
}
先序的序列化与反序列化:
//先序序列化二叉树
public static String process(Node head) {
if(head==null) {
return "#_";
}
String res=head.value+"_";
res+=process(head.left);
res+=process(head.right);
return res;
}
//反序列化
public static Node recover(String str) {
String[] split = str.split("_");
Queue<String> queue=new LinkedList<String>();
for(int i=0;i<split.length;i++) {
queue.add(split[i]);
}
return reconProOrder(queue);
}
public static Node reconProOrder(Queue <String> queue) {
String value=queue.poll();
if(value.equals("#")) {
return null;
}
Node head=new Node(Integer.valueOf(value));
head.left=reconProOrder(queue);
head.right=reconProOrder(queue);
return head;
}
按层序列化与反序列化:
序列化,在进行将左右节点放入队列的时候判断,如果为空连接空表示的字符串,不为空连接不为空的字符串
public static String serialByLevel(Node head) {
if (head == null) {
return "#!";
}
String res = head.value + "!";
Queue<Node> queue = new LinkedList<Node>();
queue.offer(head);
while (!queue.isEmpty()) {
head = queue.poll();
if (head.left != null) {
res += head.left.value + "!";
queue.offer(head.left);
} else {
res += "#!";
}
if (head.right != null) {
res += head.right.value + "!";
queue.offer(head.right);
} else {
res += "#!";
}
}
return res;
}