本文主要参考资料:https://mp.weixin.qq.com/s?__biz=MzUxNjY5NTYxNA==&mid=2247484654&idx=1&sn=0c22c8b8771acc2387bf37ac255749f0&scene=21#wechat_redirect
深度遍历
递归遍历
递归算法的三要素
- 确定递归函数的参数和返回值
- 确定终止条件:如果递归没有终止,操作系统的内存栈必然就会溢出。
- 确定单层递归的逻辑:确定每一层递归需要处理的信息,可能会重复调用自己来实现递归
树结构
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
val = x;
}
}
二叉树递归遍历
- 前序遍历
- 中序遍历
- 后序遍历
二叉树迭代遍历
1. 先序遍历
思路:重复以下步骤,直至node==null&&s.empty()
1)循环将node的左链(同色为同一左链)存入栈中,并在存栈(1)后访问node
2)若到达当前node的左链末端(null),若栈不空,则取出栈中node.right赋值node
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new Stack<Integer>();
Stack<TreeNode> s = new Stack<TreeNode>();
TreeNode p = root;
while (!s.empty() || p != null) {
while (p != null) {
s.push(p);
res.add(p.val);
p = p.left;
}
if (!s.empty()) {
p = s.peek();
s.pop();
p = p.right;
}
}
return res;
}
2. 中序遍历
思路:重复以下步骤,直至node==null&&s.empty()
1)循环将node的左链(同色为同一左链)存入栈(1)中
2)若到达node的左链末端且若栈不空,则弹栈(2)并访问node,将node.right赋值node
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new Stack<Integer>();
Stack<TreeNode> s = new Stack<TreeNode>();
TreeNode p = root;
while (!s.empty() || p != null) {
while (p != null) {
s.push(p);
p = p.left;
}
if (!s.empty()) {
p = s.peek();
s.pop();
res.add(p.val);
p = p.right;
}
}
return res;
}
3. 后序遍历
思路:重复以下步骤,直至node==null&&s.empty()
1)循环将node的左链(同色为同一左链)存入栈(1)中
2)若到达node的左链末端且若栈不空,则查看栈顶node
i) 若其right未被访问(2),则将node.right赋值给node
ii)若其right已被访问(3),则弹栈并访问node
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new Stack<Integer>();
Stack<TreeNode> s = new Stack<TreeNode>();
TreeNode r = null;
TreeNode p = root;
while (!s.empty() || p != null) {
if(p != null) {
s.push(p);
p = p.left;
}
else{
p = s.peek();
if(p.right==null||r==p.right) {
s.pop();
res.add(p.val);
r=p;
p=null;//再次引发出栈,也可以导致循环结束
}
else {
p = p.right;
}
}
}
return res;
}
二叉树morris遍历
1. morris实现原理
1)如果cur无左孩子,cur向右移动(cur=cur.right)
2)如果cur有左孩子,找到cur左子树上最右的节点,记为mostright
如果mostright的right指针指向空,让其指向cur,并设置cur=cur.left
如果mostright的right指针指向cur,让其指向空,并设置cur=cur.right
public static void morrisPre(Node head) {
Node cur = head;
Node mostRight = null;
while (cur != null){
mostRight = cur.left;
if(mostRight != null){
while (mostRight.right !=null && mostRight.right != cur){
mostRight = mostRight.right;
}
if(mostRight.right == null){
mostRight.right = cur;
System.out.print(cur.value+" ");
cur = cur.left;
continue;
}else {
mostRight.right = null;
}
}else {
System.out.print(cur.value + " ");
}
cur = cur.right;
}
}
3.morris中序遍历
public static void morrisIn(Node head) {
Node cur = head;
Node mostRight = null;
while (cur != null){
mostRight = cur.left;
if(mostRight != null){
while (mostRight.right !=null && mostRight.right != cur){
mostRight = mostRight.right;
}
if(mostRight.right == null){
mostRight.right = cur;
cur = cur.left;
continue;
}else {
mostRight.right = null;
}
}
System.out.print(cur.value+" ");
cur = cur.right;
}
System.out.println();
}
4.morris后序遍历
public static void morrisPos(Node head) {
Node cur = head;
Node mostRight = null;
while (cur != null){
mostRight = cur.left;
if(mostRight != null){
while (mostRight.right !=null && mostRight.right != cur){
mostRight = mostRight.right;
}
if(mostRight.right == null){
mostRight.right = cur;
cur = cur.left;
continue;
}else {
mostRight.right = null;
printEdge(cur.left);
}
}
cur = cur.right;
}
printEdge(head);
System.out.println();
}
public static void printEdge(Node node){
Node tail =reverseEdge(node);
Node cur = tail;
while (cur != null ){
System.out.print(cur.value+" ");
cur =cur.right;
}
reverseEdge(tail);
}
public static Node reverseEdge(Node node){
Node pre = null;
Node next = null;
while (node != null){
next = node.right;
node.right = pre;
pre = node;
node = next;
}
return pre;
}
广度遍历
思路:当cur==rear时,该层遍历结束
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
if(root==null){
return res;
}
LinkedList<TreeNode> queue = new LinkedList<>();
List<Integer> partRes = new ArrayList<>();
TreeNode rear = root;
queue.add(root);
while(!queue.isEmpty()){
TreeNode cur = queue.poll();
partRes.add(cur.val);
if(cur.left != null){
queue.add(cur.left);
}
if(cur.right!=null){
queue.add(cur.right);
}
if(cur == rear){
res.add(partRes);
partRes=new ArrayList<>();
if(!queue.isEmpty())
rear=queue.getLast();
}
}
return res;
}