先序遍历
先序遍历即先遍历根节点在遍历左节点和右节点,利用栈的特点先进后出可以先压根节点入栈,弹出根节点后,在把右孩子入栈,然后左孩子入栈,这样出栈顺序就是先根节点再左孩子,右孩子;
中序遍历
先把根节点入栈,然后把左节点全部压入栈中,一直到叶子节点,然后开始出栈,令右孩子成为子树根节点重复上面的步骤,最后压入栈的顺序如下图;
image.png
后序遍历
后序遍历可以仿照先序遍历,先序遍历是根左右,而后序遍历是左右根,其实先序遍历入栈是左右孩子换位,得到的结果就是根右左,这样反转得到的就是后序遍历;
层次遍历
层次遍历通过队列实现,直接从根节点开始把左右孩子放入队列中,这样每次都是上一层先进队列的先出队列;
/**先序遍历*/
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
if(!Objects.isNull(root)) {
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
TreeNode cur;
while (!stack.empty()) {
cur = stack.pop();
list.add(cur.val);
if(!Objects.isNull(cur.right)) {
stack.push(cur.right);
}
if(!Objects.isNull(cur.left)) {
stack.push(cur.left);
}
}
}
return list;
}
/**中序遍历*/
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
if(Objects.nonNull(root)) {
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while (!stack.empty() || Objects.nonNull(cur)) {
while (Objects.nonNull(cur)) {
stack.push(cur);
cur = cur.left;
}
cur = stack.pop();
list.add(cur.val);
cur = cur.right;
}
}
return list;
}
/**后序遍历*/
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
if(!Objects.isNull(root)) {
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
TreeNode cur;
while (!stack.empty()) {
cur = stack.pop();
list.add(cur.val);
if(!Objects.isNull(cur.left)) {
stack.push(cur.left);
}
if(!Objects.isNull(cur.right)) {
stack.push(cur.right);
}
}
}
Collections.reverse(list);
return list;
}
/**层次遍历*/
public List<Integer> levelOrder(TreeNode root) {
List<Integer> list = new ArrayList<>();
if(Objects.nonNull(root)) {
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
TreeNode cur;
while (!queue.isEmpty()) {
cur = queue.poll();
list.add(cur.val);
if(Objects.nonNull(cur.left)) {
queue.offer(cur.left);
}
if(Objects.nonNull(cur.right)) {
queue.offer(cur.right);
}
}
}
return list;
}
网友评论