三色法遍历二叉树
今天群里大佬说三色法遍历二叉树,前序遍历、中序遍历、后续遍历只需要改一点就行,对这个方法非常好奇
算法介绍
我们知道垃圾回收算法中,有一种算法叫三色标记法。 即:
- 用白色表示尚未访问
- 灰色表示尚未完全访问子节点
- 黑色表示子节点全部访问
那么我们可以模仿其思想,使用双色标记法来统一三种遍历。
其核心思想如下:
- 使用颜色标记节点的状态,新节点为白色,已访问的节点为灰色。
- 如果遇到的节点为白色,则将其标记为灰色,然后将其右子节点、自身、左子节点依次入栈。
- 如果遇到的节点为灰色,则将节点的值输出。
用三色法写个中序遍历
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
WHITE, GRAY = 0, 1
res = []
stack = [(WHITE, root)]
while stack:
color, node = stack.pop()
if node is None: continue
if color == WHITE:
stack.append((WHITE, node.right))
stack.append((GRAY, node))
stack.append((WHITE, node.left))
else:
res.append(node.val)
return res
吐槽一下,用python写算法真的赖皮
因为用的是栈,所以会先右边再左边(先进后出)
试着翻译成java的
public static List<Integer> inorderTraversal(TreeNode root) {
final int white=0;
final int gray=1;
List<Integer> res=new ArrayList<>();
Object[] tuple=new Object[2];
Stack<Object[]> stack=new Stack<>();
tuple[0]=white;
tuple[1]=root;
stack.add(tuple);
while(!stack.isEmpty()){ // 栈空跳出循环
tuple=stack.pop();
int color=(int)tuple[0];
TreeNode node = (TreeNode)tuple[1];
if (node==null) continue;
if (color==white){
stack.add(new Object[]{white, node.right});//因为使用stack做的,先进后出,所以先走右边
stack.add(new Object[]{gray,node});
stack.add(new Object[]{white,node.left});
}
if (color==gray)
res.add(node.val);
}
return res;
}
遇到的问题:
开始只用一个数组存颜色和节点的关系,所以数组中放的都是最后一次更新的结果,所以每次都要new数组。创建匿名数组的方法
new Object[] {初始值}
经过实践发现用队列写好像不对,队列把最后一次处理的放到后边去了
public static List<Integer> inorderTraversal(TreeNode root) {
final int white=0;
final int gray=1;
List<Integer> res=new ArrayList<>();
Object[] tuple=new Object[2];
Queue<Object[]> queue=new LinkedList<>();
//Map<Integer,TreeNode> map=new HashMap<>();//存关系,可以用Object类的数组,但是取出的时候要强转
tuple[0]=white;
tuple[1]=root;
queue.add(tuple);
while(!queue.isEmpty()){ // 栈空跳出循环
tuple=queue.poll();
int color=(int)tuple[0];
TreeNode node = (TreeNode)tuple[1];
if (node==null) continue;
if (color==white){
queue.add(new Object[]{white,node.left});
queue.add(new Object[]{gray,node});
queue.add(new Object[]{white, node.right});
}
if (color==gray)
res.add(node.val);
}
return res;
}
测试的树
倒数第二次队列中是[(while,3),(gray,2),null]
,这个时候3出队列,进过循环之后,队列变成了[(gray,2),null,null,(gray,3),null]
。所以就不对了。。。所以该怎么改呢???