前中后序遍历的非递归实现均采用栈结构实现,层次遍历采用队列实现。
先序遍历:
思路:
1最开始根节点入栈
2循环中每次向栈中取一个节点,访问该节点。将其左右子树入栈,直至栈为空为止。
注意:由于栈是先进后出的数据结构,先将右子树入栈,再将左子树入栈,才能得到中左右的访问顺序。
代码:
//先序遍历
public static void travelFirst(TreeNode root){
Stack<TreeNode> stack = new Stack();
stack.push(root);
while(!stack.isEmpty()){
TreeNode node = stack.pop();
System.out.println(node.val);
if(node.right!=null){
stack.push(node.right);
}
if(node.left!=null){
stack.push(node.left);
}
}
}
中序遍历:
思路:采用和后序遍历一样的思路,借鉴了https://www.cnblogs.com/rain-lei/p/3705680.html中实现后序遍历的方法2.
每次节点入栈都入栈两次,循环中每次都取一个节点,取出后如果该节点等于栈顶节点,表示该节点的左右子树还未访问,则先该节点左子树入栈,否则直接访问该节点,然后将右子树入栈。
代码:
//中序遍历
public static void travelMid(TreeNode root) {
Stack<TreeNode> stack = new Stack();
stack.push(root);
stack.push(root);
while (!stack.isEmpty()) {
TreeNode node = stack.pop();
if (stack.size() > 0 && node == stack.peek()) {
if (node.left != null) {
stack.push(node.left);
stack.push(node.left);
}
} else {
System.out.println(node.val);
if (node.right != null) {
stack.push(node.right);
stack.push(node.right);
}
}
}
}
后序遍历:
思路;后序遍历的思路和中序类似。
每次节点入栈都入栈两次,循环中每次都取一个节点,取出后如果该节点等于栈顶节点,表示该节点的左右子树还未访问,则先该节点左子树入栈,然后将右子树入栈,否则直接访问该节点。
代码:
//后序遍历
public static void travelLast(TreeNode root) {
Stack<TreeNode> stack = new Stack();
stack.push(root);
stack.push(root);
while (!stack.isEmpty()) {
TreeNode node = stack.pop();
if (stack.size() > 0 && node == stack.peek()) {
if (node.right != null) {
stack.push(node.right);
stack.push(node.right);
}
if (node.left != null) {
stack.push(node.left);
stack.push(node.left);
}
} else {
System.out.println(node.val);
}
}
}
层次遍历:
思路:按照树的深度依次向下遍历,采用队列(本例中采用linkedlist实现队列)作为辅助结构。
1将根节点入队
2循环从队列中取出元素,访问该元素,并将该元素左右节点入队,直到队列为空。
//层次遍历
public static void travelLevel(TreeNode root){
LinkedList<TreeNode> list = new LinkedList();
list.offer(root);
while(!list.isEmpty()){
TreeNode node = list.poll();
System.out.println(node.val);
if(node.left!=null) {
list.offer(node.left);
}
if(node.right!=null){
list.offer(node.right);
}
}
}
测试代码:
public static void main(String[] args) {
TreeNode node1 = new TreeNode(1);
TreeNode node2 = new TreeNode(2);
TreeNode node3 = new TreeNode(3);
TreeNode node4 = new TreeNode(4);
TreeNode node5 = new TreeNode(5);
TreeNode node6 = new TreeNode(6);
TreeNode node7 = new TreeNode(7);
node1.left = node2;
node1.right = node3;
node2.left = node4;
node2.right = node5;
node3.left = node6;
node3.right = node7;
travelLevel(node1);
}
public static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
val = x;
}
}
附一个非递归获取树深度的方法(基于层次遍历)
思路:与层次遍历不同的是,每次入队(最外层一次循环)都将上一层的节点全都出队(借助变量len实现),使得每次循环中队列中都只有一层的节点,则每次循环depth都加1。
//通过层次遍历来得到树的深度
public static int treeDepthByLevel(TreeNode root){
LinkedList<TreeNode> list = new LinkedList();
list.offer(root);
int depth = 0;
while(!list.isEmpty()){
int len = list.size();
depth++;
while((len--)>0){
TreeNode node = list.poll();
if(node.left!=null){
list.offer(node.left);
}
if(node.right!=null){
list.offer(node.right);
}
}
}
return depth;
}