层次遍历:
层次遍历二叉树,使用了队列结构-Queue(先进先出)来实现。
先将根节点入队列,只要队列不为空,然后出队列并访问,接着将访问节点的左右子树依次入队列。如此操作,可以保证上层的节点一定会在下层之前输出。
//层次
public int[] levelOrder(TreeNode root) {
if(root==null) return new int[0];
List<Integer> list = new ArrayList<>();
Queue<TreeNode> queue = new LinkedList<>();
//TreeNode node = root;
queue.add(root);
while(!queue.isEmpty()){
TreeNode node = queue.poll();
list.add(node.val);
if(node.left!=null){
queue.add(node.left);
}
if(node.right!=null){
queue.add(node.right);
}
}
int [] res = new int [list.size()];
for(int i=0;i<res.length;i++){
//当i为1时,获取list中的第一个元素
res[i]=list.get(i);
}
return res;
}
先序、中序、后序遍历关系:
先序遍历(根左右):
考察到一个节点后,立刻输出该节点的值,然后继续遍历其左右子树;
根在前,从左往右,一棵树的根永远在左子树前面,左子树又永远在右子树前面;
核心:先输出自己,再遍历子树。
中序遍历(左根右):考察到一个节点后,将其暂存,遍历完左子树后,再输出该节点的值,然后遍历右子树;
根在中,从左往右,一棵树的左子树永远在根前面,根永远在右子树前面;
核心:自己的左子没有数据,才将自己输出。
后序遍历(左右根):考察到一个节点后,将其暂存,遍历完左右子树后,再输出该节点的值;
根在后,从左往右,一棵树的左子树永远在右子树前面,右子树永远在根前面;
核心:自己的左子和右子都没有数据,才将自己输出。
递归:先中后序遍历
public void preOrder(TreeNode root){
List<TreeNode> list = new ArrayList<>();
if(root==null) return;
list.add(root);
if(root.left!=null){
preOrder(root.left);
}
if(root.right!=null){
preOrder(root.right);
}
}
//递归 -中序
public void inOrder(TreeNode root){
List<TreeNode> list = new ArrayList<>();
if(root==null) return;
if(root.left!=null){
preOrder(root.left);
}
list.add(root);
if(root.right!=null){
preOrder(root.right);
}
}
//递归 -后续
public void postOrder(TreeNode root){
List<TreeNode> list = new ArrayList<>();
if(root==null) return;
if(root.left!=null){
preOrder(root.left);
}
if(root.right!=null){
preOrder(root.right);
}
list.add(root);
}
非递归:先中后遍历
//非递归-先序
public void preOrder(TreeNode root){
List<Integer> list = new ArrayList<>();
Stack<TreeNode> stack = new Stack<>();
while(root!=null||!que.isEmpty()){
//一直往二叉树的左子树上走
while(root!=null){
list.add(root.val);
stack.push(root);
root = root.left;
}
//左边的节点都走完了 改变节点方向
if(!stack.isEmpty()){
root = stack.pop();
root=root.right;
}
}
}
//非递归-中序
public void inOrder(TreeNode root){
List<Integer> list = new ArrayList<>();//结果
Stack<TreeNode> stack = new Stack<>();
while(root!=null||!que.isEmpty()){
一直向左,但是先不存入
while(root!=null){
stack.push(root);
root = root.left;
}
//左边的节点都走完了 存入list并 改变节点方向
if(!stack.isEmpty()){
root = stack.pop();
list.add(root.val);
root=root.right;
}
}
}
//非递归-后序
public void postOrder(TreeNode root){
List<Integer> list = new ArrayList<>();//结果
Stack<TreeNode> stack = new Stack<>();
while(root!=null||!que.isEmpty()){
//一直向右
while(root!=null){
list.add(root.val)
stack.push(root);
root = root.right;
}
if(!stack.isEmpty()){
root = stack.pop();
root=root.left;
}
}
}