二叉树的先序、中序、后序遍历是DFS(深度优先搜索)思想;层次遍历是BFS(广度优先搜索)思想。一般DFS用递归或栈实现;BFS用队列实现。
private static List<Node> nodeList=null;
//定义二叉树
private static class Node{
private Node leftChild,rightChild;
private int data;
public Node(int newData){
leftChild=null;
rightChild=null;
data=newData;
}
}
//构建二叉树
public static void createBinaryTree(int[] objs){
nodeList=new ArrayList<Node>();
for(int o:objs){
nodeList.add(new Node(o));
}
for(int i=0;i<objs.length/2;i++){
nodeList.get(i).leftChild=nodeList.get(i*2+1);
if(i*2+2<nodeList.size()) {
nodeList.get(i).rightChild = nodeList.get(i * 2 + 2);
}
}
}
先序遍历:根节点->左子树->右子树
//先序遍历 递归实现
public static void pre(Node node){
if(node!=null){
System.out.print(node.data+" ");
pre(node.leftChild);
pre(node.rightChild);
}
}
//先序遍历 非递归实现
public static void pre2(Node node){
Stack<Node> stack=new Stack<Node>();
while(node!=null || !stack.empty()){
if(node!=null){
System.out.print(node.data+" ");
stack.push(node);
node=node.leftChild;
}else{
Node tmpNode=stack.pop();
node=tmpNode.rightChild;
}
}
}
中序遍历:左子树->根节点->右子树
//中序遍历 递归实现
public static void mid(Node node){
if(node!=null){
mid(node.leftChild);
System.out.print(node.data+" ");
mid(node.rightChild);
}
}
//中序遍历 非递归实现
public static void mid2(Node node){
Stack<Node> stack=new Stack<Node>();
while(node!=null || !stack.empty()){
if(node!=null){
stack.push(node);
node=node.leftChild;
}else{
Node tmpNode=stack.pop();
System.out.print(tmpNode.data+" ");
node=tmpNode.rightChild;
}
}
}
后序遍历:左子树->右子树->根节点
非递归实现思路:1、采用根、右、左的遍历方法,然后反转;2、建立一个指向前一个节点的指针,标记右孩子是否被访问
//后序遍历 递归实现
public static void post(Node node){
if(node!=null){
post(node.leftChild);
post(node.rightChild);
System.out.print(node.data+" ");
}
}
//后序遍历 非递归实现1
public static void post2(Node node) {
Stack<Node> stack=new Stack<Node>();
List<Integer> list=new ArrayList<Integer>();
while(node!=null || !stack.isEmpty()){
if(node!=null){
list.add(node.data);
stack.push(node);
node=node.rightChild;
}else{
Node tmp=stack.pop();
node=tmp.leftChild;
}
}
Collections.reverse(list);
for(int i=0;i<list.size();i++){
System.out.print(list.get(i)+" ");
}
}
//后序遍历 非递归实现2
public static void post3(Node node){
Stack<Node> stack=new Stack<Node>();
Node p=null;
while(node!=null || !stack.empty()){
if(node!=null){
stack.push(node);
node=node.leftChild;
}else{//node==null && !stack.empty()
Node tmpNode=stack.peek().rightChild;
if(tmpNode==null || tmpNode==p){//tmpNode==p为了避免重复访问同一个元素而陷入死循环中
node=stack.pop();
System.out.print(node.data+" ");
p=node;
node=null;
}else{
node=tmpNode;
}
}
}
}
层次遍历
Java中实现队列一般都是用LinkedList,LinkedList既实现List接口,能对它进行列表操作;又实现了Deque接口,能将它当队列使用。作为List使用时,一般采用add/get方法来压入/获取对象。作为Queue使用时,才会采用offer/poll/take等方法。
//层次遍历
public static void levalOrder(Node node){
if(node==null) return;
Queue<Node> q=new LinkedList<Node>();
q.offer(node);
Node temp=null;
while(!q.isEmpty()){
temp=q.poll();
System.out.print(temp.data+" ");
if(temp.leftChild!=null){
q.offer(temp.leftChild);
}
if(temp.rightChild!=null){
q.offer(temp.rightChild);
}
}
}
测试
public static void main(String[] args) {
int[] node=new int[]{1,2,3,4,5,6};
//创建二叉树
// 1
// / \
// 2 3
// / \ /
// 4 5 6
createBinaryTree(node);
//根节点
Node root=nodeList.get(0);
//先序遍历(根节点->左子树->右子数):1 2 4 5 3 6
System.out.println("先序遍历");
pre2(root);
//中序遍历(左子树->根节点->右子数):4 2 5 1 6 3
System.out.println("\n中序遍历");
mid2(root);
//后序遍历(左子树->右子树->根节点):4 5 2 6 3 1
System.out.println("\n后序遍历");
post2(root);
//层次遍历:1 2 3 4 5 6
System.out.println("\n层次遍历");
levalOrder(root);
}