1.前序遍历
递归:
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list=new ArrayList<>();
preL(root,list);
return list;
}
public void preL(TreeNode node,List<Integer> list)
{
if(node==null)
{
return;
}
list.add(node.val);
preL(node.left,list);
preL(node.right,list);
}
非递归:
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list=new ArrayList<>();
if(root==null)
{
return list;
}
Stack<TreeNode> stack=new Stack<>();
stack.push(root);
while(!stack.isEmpty())
{
TreeNode node=stack.pop();
list.add(node.val);
//因为栈是先进先出原则,如果先放左节点,会后出来
if(node.right!=null)
{
stack.push(node.right);
}
if(node.left!=null)
{
stack.push(node.left);
}
}
return list;
}
2.中序遍历
递归:
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> list=new LinkedList<Integer>();
inorderTraversal(root,list);
return list;
}
public void inorderTraversal(TreeNode root,List<Integer> list)
{
if(root==null)
{
return;
}
inorderTraversal(root.left,list);
list.add(root.val);
inorderTraversal(root.right,list);
}
非递归:使用栈
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> list=new LinkedList<Integer>();
Stack<TreeNode> stack=new Stack<TreeNode>();
TreeNode cur=root;
while(cur!=null || !stack.isEmpty())
{
if(cur!=null)
{
stack.push(cur);
cur=cur.left;
}
else
{
cur=stack.pop();
list.add(cur.val);
cur=cur.right;
}
}
return list;
}
3.后序遍历
递归
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> list=new ArrayList<>();
post(root,list);
return(list);
}
public void post(TreeNode root,List<Integer> list)
{
if(root==null)
{
return;
}
post(root.left,list);
post(root.right,list);
list.add(root.val);
}
非递归:
(1)借助双向队列,先让根节点到左节点都进入队列,然后从后面取出(peek,只是取出栈顶元素,而不是弹出),然后判断这个节点(左节点肯定是空的)这个节点的右节点是不是空的或者是不是访问过的,是的话,则在这个里面才弹出,并将前节点设置成这个节点。不是的话,则访问右节点。
public List<Integer> postorderTraversal(TreeNode root) {
TreeNode p=root;
TreeNode r=null;
List<Integer> res=new ArrayList<>();
Deque<TreeNode> queue=new ArrayDeque<>();
while(!queue.isEmpty() || p!=null)
{
if(p!=null)
{
queue.push(p);
p=p.left;
}
else
{
//左边的先进入队列,然后从队列的后面开始取元素,然后判断这个的右节点有没有访问过
p=queue.peek();
//右节点为空,或者右节点是访问过的
if(p.right==null || p.right==r)
{
res.add(p.val);
//将访问节点进行标记
r=p;
queue.pop();
p=null;
}
else{
p=p.right;
}
}
}
return res;
}
(2)借助先序遍历的方法,就是将根左右改成根右左,然后将List逆序就可。可以在放入list的时候直接指定位置,每次都是第一个。
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> list=new ArrayList<>();
if(root==null)
{
return list;
}
Stack<TreeNode> stack=new Stack<>();
stack.push(root);
while(!stack.isEmpty())
{
TreeNode node=stack.pop();
list.add(0,node.val);
if(node.left!=null)
{
stack.push(node.left);
}
if(node.right!=null)
{
stack.push(node.right);
}
}
return list;
}
4.层次遍历
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res=new ArrayList<>();
Queue<TreeNode> queue=new LinkedList<>();
if(root==null)
{
return res;
}
queue.add(root);
while(!queue.isEmpty())
{
int size=queue.size();
List<Integer> list = new ArrayList<Integer>();
while(size>0){
TreeNode node=queue.poll();
list.add(node.val);
if(node.left!=null)
{
queue.add(node.left);
}
if(node.right!=null)
{
queue.add(node.right);
}
size--;
}
res.add(list);
}
return res;
}