1. 前序遍历
2. 中序遍历
3. 后序遍历
4. 层序遍历
这三种方式分别可以用递归和非递归的方式实现
前序遍历:遍历的前中后表示的是访问根节点的顺序,前就是先访问根节点然后左右节点,遍历的时候左结点可能是一颗左子树,这颗左子树也要按照根左右的顺序遍历,同理右结点。我们可以通过下图看的更清楚黑色箭头表示的是遍历顺序ABDECFG
递归方式:
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {}
TreeNode(int val) { this.val = val; }
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
public static void preOrder(TreeNode tree) {
if (tree == null){
return;
}
System.out.println(tree.val);
preOrder(tree.left);
preOrder(tree.right);
}
非递归方式:可以使用一个栈解决问题,
1.先将根结点入栈,然后根结点出栈,访问结点。
2.将根节点的右子树左子树入栈。
3.栈不空,栈顶元素出栈,访问结点,该结点的右子树,左子树入栈。
4.重复3,直到栈为空。
public void preOrder(TreeNode tree) {
Stack<TreeNode> stack = new Stack<>();
stack.push(tree);
while (!stack.empty()) {
TreeNode t1 = stack.pop();
System.out.println(t1.val);
if (t1.right != null) {
stack.push(t1.right);
}
if (t1.left != null) {
stack.push(t1.left);
}
}
}
中序遍历:遍历先访问左结点然后访问根结点然后再访问右结点,遍历的时候左结点可能是一颗左子树,这颗左子树也要按照左根右的顺序遍历,同理右结点。看下图我们可以很清楚的看到,遍历顺序为DBEADCG
递归方式:
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {}
TreeNode(int val) { this.val = val; }
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
public static void inorderTraversal(TreeNode tree) {
if (tree == null){
return;
}
inorderTraversal(tree.left);
System.out.println(tree.val);
inorderTraversal(tree.right);
}
非递归方式:使用栈解决
1.若有左子树,将左子树的左结点全部入栈,直到到达最左侧结点。
2.最左侧结点出栈,访问最左侧结点。
3.看看该结点有没有右子树有的话重复1,2。没有的话继续出栈,直到栈空
public void inOrderTraversal(TreeNode tree) {
Stack<TreeNode> stack = new Stack<>();
while (tree != null || !stack.isEmpty()) {
while (tree != null) {
stack.push(tree);
tree = tree.left;
}
if (!stack.isEmpty()) {
tree = stack.pop();
System.out.println(tree.val);
tree = tree.right;
}
}
}
后序遍历:遍历先访问左结点然后访问右结点然后再访问根结点,遍历的时候左结点可能是一颗左子树,这颗左子树也要按照左右根的顺序遍历,同理右结点。看下图我们可以很清楚的看到,遍历顺序为DEBFGCA
递归方式:
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {}
TreeNode(int val) { this.val = val; }
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
public static void postorderTraversal(TreeNode tree) {
if (tree == null){
return;
}
postorderTraversal(tree.left);
postorderTraversal(tree.right);
System.out.println(tree.val);
}
非递归方式:前序遍历是根左右,我们可以通过求根右左,然后将顺序逆转,就是后序遍历的方法。
1.根结点入栈。
2.栈不为空出栈,如果该结点都存在左右结点,将该结点的左结点,右节点分别入栈。
3.重复2。
4.逆序输出遍历的顺序。
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {}
TreeNode(int val) { this.val = val; }
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
public void postorderTraversal(TreeNode tree) {
Stack<TreeNode> stack = new Stack<>();
List<Integer> res = new ArrayList<>();
if (tree == null)
return;
stack.push(tree);
while (!stack.empty()) {
TreeNode t1 = stack.pop();
res.add(t1.val);
if (t1.left != null) {
stack.push(t1.left);
}
if (t1.right != null) {
stack.push(t1.right);
}
}
Collections.reverse(res);
for(Integer num:res){
System.out.println(num);
}
}
层序遍历:就是一层一层的遍历,下图可以清楚的表示:ABCDEFG,这个实现的话我们可以借助队列来实现。
1.根结点如队列。
2.队列不为空,出队,如果该结点左右结点不为空,入队。
3.重复2,直至队列为空。
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {}
TreeNode(int val) { this.val = val; }
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
public void levelOrder(TreeNode root) {
//边界条件判断
if (root == null)
return;
//队列
Queue<TreeNode> queue = new LinkedList<>();
//根节点入队
queue.add(root);
//如果队列不为空就继续循环
while (!queue.isEmpty()) {
//出队
TreeNode node = queue.poll();
System.out.println(node.val);
//左右子节点如果不为空就加入到队列中
if (node.left != null)
queue.add(node.left);
if (node.right != null)
queue.add(node.right);
}
}
}