博客
关于我
java遍历二叉树
阅读量:202 次
发布时间:2019-02-28

本文共 3614 字,大约阅读时间需要 12 分钟。

问题分析

由于不论先序还是中序、后序遍历,在程序运行流程上没有本质区别,区别仅仅是访问语句的执行时间点。因此,只要有了先序的程序流程,改变一下访问语句代码位置,就可以实现前三种遍历方式。

先序遍历(非递归)

先序遍历是从树的根节点开始,依次访问左节点和右节点。非递归实现使用栈来模拟调用栈,确保每个节点只被访问一次。

public void visitFirst_N(Node tree) {
if (tree != null) {
Stack
stack = new Stack<>();
stack.push(tree);
Node current = tree;
while (current != null) {
System.out.print(current.value + " ");
current = current.left;
if (current != null) {
stack.push(current);
} else {
while (!stack.isEmpty()) {
Node node = stack.pop();
current = node.right;
if (current != null) {
stack.push(current);
break;
}
}
}
}
}
}

中序遍历(非递归)

中序遍历是从树的根节点开始,先访问左节点,后访问右节点。非递归实现仍然使用栈,但处理方式有所不同。

public void midTest(Node tree) {
if (tree != null) {
Stack
stack = new Stack<>();
stack.push(tree);
Node current = tree;
while (current != null) {
current = current.left;
if (current != null) {
stack.push(current);
} else {
while (!stack.isEmpty()) {
Node node = stack.pop();
System.out.print(node.value + " ");
current = node.right;
if (current != null) {
stack.push(current);
break;
}
}
}
}
}
}

后序遍历(非递归)

后序遍历是从树的根节点开始,先访问右节点,再访问左节点。由于栈的先进后出特性,需要额外处理栈中的节点,确保左节点在栈底部。

public void LastTest(Node tree) {
if (tree != null) {
Stack
stack = new Stack<>();
stack.push(tree);
Node current = tree;
while (current != null) {
current = current.left;
if (current != null) {
stack.push(current);
} else {
while (!stack.isEmpty()) {
Node node = stack.peek();
current = node.right;
if (current == null) {
Node x = stack.pop();
System.out.print(x.value + " ");
Node y = stack.pop();
if (y.left == x) {
stack.push(y);
current = y.right;
} else {
Node k = stack.peek();
System.out.print(y.value + " ");
if (k.right == y) {
while (!stack.isEmpty()) {
System.out.print(stack.pop().value + " ");
}
return;
}
current = k.right;
}
}
if (current != null) {
stack.push(current);
break;
}
}
}
}
}
}

层次遍历(非递归)

层次遍历是按层访问树节点。使用队列来实现,先处理队列中的节点,输出其值,然后将左孩子和右孩子入队。

private void visitLevel(Node x) {
Queue
queue = new Queue<>();
while (x != null) {
System.out.print(x.value + " ");
if (x.left != null) {
queue.enqueue(x.left);
}
if (x.right != null) {
queue.push(x.right);
}
x = queue.deQueue();
}
}

通过上述实现,可以清晰地看到不同遍历方式在非递归情况下的实现差异。

转载地址:http://mpvi.baihongyu.com/

你可能感兴趣的文章
Nginx 动静分离与负载均衡的实现
查看>>
Nginx 反向代理 MinIO 及 ruoyi-vue-pro 配置 MinIO 详解
查看>>
nginx 反向代理 转发请求时,有时好有时没反应,产生原因及解决
查看>>
Nginx 反向代理解决跨域问题
查看>>
Nginx 反向代理配置去除前缀
查看>>
nginx 后端获取真实ip
查看>>
Nginx 学习总结(16)—— 动静分离、压缩、缓存、黑白名单、性能等内容温习
查看>>
Nginx 学习总结(17)—— 8 个免费开源 Nginx 管理系统,轻松管理 Nginx 站点配置
查看>>
Nginx 常用配置清单
查看>>
nginx 常用配置记录
查看>>
Nginx 我们必须知道的那些事
查看>>
Nginx 的 proxy_pass 使用简介
查看>>
Nginx 的配置文件中的 keepalive 介绍
查看>>
Nginx 负载均衡与权重配置解析
查看>>
Nginx 负载均衡详解
查看>>
nginx 配置 单页面应用的解决方案
查看>>
nginx 配置https(一)—— 自签名证书
查看>>
nginx 配置~~~本身就是一个静态资源的服务器
查看>>
Nginx 配置解析:从基础到高级应用指南
查看>>
nginx+Tomcat性能监控
查看>>