1.先序
递归:
public void dfs(TreeNode root, List<Integer> list){
if(root != null){
list.add(root.val);
dfs(root.left,list);
dfs(root.right,list);
}
}
迭代:
public List<Integer> preorderTraversal2(TreeNode root) {
List<Integer> list = new ArrayList<Integer>();
Deque<TreeNode> stack = new ArrayDeque<>();
while (!stack.isEmpty()||root!=null){
while (root!=null){
stack.push(root);
list.add(root.val);
root = root.left;
}
root = stack.pop();
root = root.right;
}
return list;
}
Morris:
morris遍历的实现原则
记作当前节点为root。
- 如果root无左孩子,root向右移动(root = root.right)
- 如果root有左孩子,找到root左子树上最右的节点,记为mostright
- 如果mostright的right指针指向空,让其指向cur,cur向左移动(root = root.left)
- 如果mostright的right指针指向root,让其指向空,cur向右移动(root=root.right)
实现以上的原则,即实现了morris遍历。
morris遍历的实质
建立一种机制,对 于没有左子树的节点只到达一次,对于有左子树的节点会到达两次
先序代码:右左孩子的情况下第一次访问建立线索进入左孩子,第二次访问断开线索进入右孩子
public List<Integer> preorderTraversal4(TreeNode root) {
List<Integer> list = new ArrayList<Integer>();
TreeNode link = null;
while (root != null) {
if (root.left != null) {//有左孩子
link = root.left;
while (link.right != null && link.right != root) {
//找到root中序遍历的前驱结点
link = link.right;
}
if (link.right == null) {//第一次访问root,link访问root前驱建立链接
list.add(root.val);
link.right = root;
root = root.left;
continue;
} else {//第二次访问root和link访问root前驱
link.right = null;
}
}else {
//非第二次进入有左孩子结点
list.add(root.val);
}
//无左孩子,或者有左孩子但是是第二次访问
root = root.right;
}
return list;
}
线索化:
public List<Integer> preorderTraversal3(TreeNode root) {//先序线索化
List<Integer> list = new ArrayList<Integer>();
TreeNode link = null;
TreeNode next = null;
while (root!=null){
list.add(root.val);
if(root.right != null){ //有右子树
if(root.left != null){//且有左子树
link = root.left;
//找先序遍历左后一个,建立线索指向root.right
while((link.right!= null||link.left!=null)&&link.right!=root.right){
if(link.right!=null)
link = link.right;
else
link = link.left;
}
if(link.right == null && link.left == null){
link.right = root.right;
next = root.right;
root = root.left;
}else{
root = root.right;
link.right = null;
}
}else{//有右无左
TreeNode p = root;
root = root.right;
if(root == next) p.right = null;
}
}
else//无右子树,默认进入左子树
root = root.left;
}
return list;
}