二叉数的遍历(java实现)
- 二叉树的定义
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
递归实现:
- 前序遍历的递归算法
public void preOrder(TreeNode t) {
if(t != null) {
System.out.println(t.val);
preOrder(t.left);
preOrder(t.right);
}
}
- 中序遍历的递归算法
public void inOrder(TreeNode t) {
if(t != null) {
inOrder(t.left);
System.out.println(t.val);
inOrder(t.right);
}
}
- 后序序遍历的递归算法
public void postOrder(TreeNode t) {
if(t != null) {
postOrder(t.left);
postOrder(t.right);
System.out.println(t.val);
}
}
非递归实现:
递归调用的本质是使用递归工作栈来进行数据存储, 因此将递归算法转换成非递归算法需要借用栈.
- 前序遍历的非递归算法
每向左访问一次节点, 上一个节点的右子树就会被遗弃,
小右很伤心
因此, 利用栈来存储每个节点被忘记的右子树
public void preOrder1(TreeNode t) {
TreeNode p = t; //定义一个用来遍历的指针
Stack<TreeNode> s = new Stack<>();
do {
while(p != null) {
System.out.println(p.val);
if(p.right != null)
s.push(p.right);
p = p.left;
}
p = s.pop();
}while(!s.empty());
}
- 中序遍历的非递归算法:
中序遍历要先一直向左遍历下去, 直到某个节点不存在左子树时, 才会回来访问该节点.
但是一路向左才发现一直都没有记下父节点的名字.(有了孩子忘了爹
所以同样利用栈来存储每次走过的节点
public void inOrder1(TreeNode t) {
TreeNode p = t; //定义一个用来遍历的指针
Stack<TreeNode> s = new Stack<>();
while(p != null || !s.empty()){
if(p != null){
s.push(p);
p = p.left;
}
else{
p = s.pop();
System.out.println(p.val);
p = p.right; //若不存在右子树则接着出栈访问
}
}
}
- 后序遍历的非递归算法:
后序遍历是访问完左右节点后才能访问根节点
每次操作的节点都可以视为根节点, 那么访问根节点的时候需要知道右子节点是否被访问过,
因此引入辅助指针 r 指向最近一次访问的节点
(这块不理解的可以把r指针和有关r的判断语句去掉根据实例走一遍程序就能发现漏洞: 判断节点是否存在右子树的时候会重复访问右节点)
public void postOrder1(TreeNode t) {
TreeNode p = t; //定义一个用来遍历的指针
TreeNode r = null; //辅助指针r指向最近一次访问过的节点
Stack<TreeNode> s = new Stack<>();
do {
while(p != null) {
s.push(p);
p = p.left;
}
p = s.peek(); //右节点还未访问, 所以此时只是瞄一眼, 还不能取出栈顶元素
if(p.right != null && p.right != r) {
p = p.right;
}
else { //不存在右节点或者右节点已被访问时 才能访问根节点
p = s.pop();
System.out.println(p.val);
r = p;
p = null;
}
}while(!s.empty());
}
- 层次遍历
public void levelOrder(TreeNode t) {
if(t == null) return;
TreeNode p = t;
LinkedList<TreeNode> queue = new LinkedList<>();
queue.offer(p);
while(!queue.isEmpty()) {
p = queue.poll();
System.out.println(p.val);
if(p.left != null)
queue.offer(p.left);
if(p.right != null)
queue.offer(p.right);
}
}