一 前言
树是一种逻辑结构,物理实现有连续存储方式(数组)和非连续的链表方式。最常见的是二叉树,连续存储就是按照层次遍历的方法,依次存入数组,但空的节点也必须存储,也就是说会造成空间的浪费 ,所以只适用于满二叉树和完全二叉树。
树的遍历方法 有两类,一类是深度遍历:
前序遍历:就是先遍历当前节点,再遍历左子树,最后遍历右子树 中左右 对于下图 80 55 32 60 90 96 98
中序遍历:对应的就是 左中右 32 55 60 80 90 96 98
后序遍历: 左右中 32 60 55 98 96 90 80
另一类是层次遍历
就是按层访问 80 55 90 32 60 96 98
对于第一类深度优先,是一个递归的过程,所以用递归的算法很容易。而非递归在于自己手动创建栈,实现递归过程。
二 代码实现
二叉树的遍历首先是要有一棵树,在漫画算法里有一个基于链表创建二叉树的例子。见代码:(另外要用数组描述二叉树,有两种方式,一是给出中序遍历和其它先(后)序遍历,或者就是带空节点的遍历方法 比如上图的遍历就是
{80, 55, 32, null, null, 60, null, null, 90, null, 96,null,98,null,null}
下面的算法就是基于这样的链表实现二叉树的创建的
package tree;import java.util.*;public class MyTree { int val; MyTree left; MyTree right; MyTree() { } MyTree(int val) { this.val = val; } //二叉树结构定义//根据链表创建二叉树 public static MyTree createTree(LinkedListlist) { if (list == null || list.size() == 0) return null; Integer data = list.removeFirst(); MyTree node = null; if (data != null) { node = new MyTree(data); node.left = createTree(list); node.right = createTree(list); } return node; }//前序遍历的递归版本 public static void xianXu(MyTree tree) { if (tree == null) return; System.out.print(tree.val + " "); xianXu(tree.left); xianXu(tree.right); }//中序遍历的递归版本 public static void zhongXu(MyTree tree) { if (tree == null) return; zhongXu(tree.left); System.out.print(tree.val + " "); zhongXu(tree.right); }//后序遍历的递归版本 public static void houXu(MyTree tree) { if (tree == null) return; houXu(tree.left); houXu(tree.right); System.out.print(tree.val + " "); }//先序遍历的非递归版本 public static void xianXu1(MyTree tree) { if (tree == null) return; Deque deque = new ArrayDeque<>(); MyTree node = null; deque.push(tree); while (!deque.isEmpty()) { node = deque.pop(); System.out.print(node.val + " "); if (node.right != null) deque.push(node.right); if (node.left != null) deque.push(node.left); } }//中序遍历的非递归版本 public static void zhongXu1(MyTree tree) { if (tree == null) { return; } MyTree now = tree; Deque deque = new ArrayDeque<>(); while (!deque.isEmpty() || now != null) { while (now != null) { deque.push(now); now = now.left; } now = deque.pop(); System.out.print(now.val + " "); now = now.right; } }//后序遍历的非递归版本 public static void houXu1(MyTree tree) { if (tree == null) return; Deque deque = new ArrayDeque<>(); Deque deque1 = new ArrayDeque<>(); MyTree node = null; deque.push(tree); while (!deque.isEmpty()) { node = deque.pop(); deque1.push(node.val); if (node.left != null) deque.push(node.left); if (node.right != null) deque.push(node.right); } while (!deque1.isEmpty()) System.out.print(deque1.pop() + " "); }//层次遍历 public static void cengCi(MyTree tree) { if (tree == null) return; Queue queue = new ArrayDeque<>(); MyTree now = null; queue.offer(tree); while (!queue.isEmpty()) { now = queue.poll(); System.out.print(now.val + " "); if (now.left != null) queue.offer(now.left); if (now.right != null) queue.offer(now.right); } }}
下面是测试代码:
public class TreeTest { public static void main(String[] args) { Integer[] arr = {80, 55, 32, null, null, 60, null, null, 90, null, 96,null,98,null,null}; MyTree tree=MyTree.createTree(new LinkedList<>(Arrays.asList(arr))); MyTree.xianXu(tree); System.out.println("前序递归"); MyTree.xianXu1(tree); System.out.println("前序非递归"); MyTree.zhongXu(tree); System.out.println("中序递归"); MyTree.zhongXu1(tree); System.out.println("中序非递归"); MyTree.houXu(tree); System.out.println("后序递归"); MyTree.houXu1(tree); System.out.println("后序非递归"); MyTree.cengCi(tree); System.out.println("层次遍历"); }}