编程之美-分层遍历二叉树



import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class LevelTraverseBinaryTree {

/**
* 编程之美 分层遍历二叉树
* 之前已经用队列实现过二叉树的层次遍历,但这次要求输出换行,因此要标记什么时候要换行:
* 用inCount记录某层有多少个元素,outCount记录当前输出了多少个元素;当inCount==outCount时,就说明某层元素已经完全输出,此时应该换行(outCount清零)
* 此外,观察发现,当第K层元素全部出队(并已将各自左右孩子入队)后,队列里面刚好存放了第K+1层的所有元素,不多不少,所以有:inCount = queue.size();
*
* 书上的扩展问题也很有意思(从下往上分层输出),既然是反过来输出,第一反应是利用栈
* 但同时又要记录何时换行(每行有多少个元素),只好用ArrayList模拟一个“伪栈”:
* 1、第一步操作和“从上往下分层输出”是类似的:从root开始遍历,并将所有元素放入“队列”(ArrayList),用-1表示一层的结束
* 2、输出。不是从队头开始,而是从队尾开始,依次输出
* 分析到这里,这里面的ArrayList定义为“双向队列”更合适
*/
public static void main(String[] args) {
/*
__1__
/ \
__2__ 3__
/ \ \
4 __5__ 6
7 8
*/
int[] src = { 1, 2, 3, 4, 5, 0, 6, 0, 0, 7, 8 };
LevelTraverseBinaryTree data = new LevelTraverseBinaryTree();
Node root = data.createTree(src);
data.traverseByLevelFromTop(root);
System.out.println();
data.traverseByLevelFromBottom(root);
}

/*
从上往下分层输出
1
2 3
4 5 6
7 8
*/
public void traverseByLevelFromTop(Node node) {
if (node == null) {
return;
}
LinkedList<Node> queue = new LinkedList<Node>();
queue.addLast(node);
int inCount = 1;
int outCount = 0;
while (!queue.isEmpty()) {
Node curNode = queue.pollFirst();
System.out.print(curNode.getData() + " ");
outCount++;
if (curNode.getLeft() != null) {
queue.addLast(curNode.getLeft());
}
if (curNode.getRight() != null) {
queue.addLast(curNode.getRight());
}
if (outCount == inCount) {
System.out.println();
inCount = queue.size();
outCount = 0;
}
}
}

/*
从下往上分层输出
7 8
4 5 6
2 3
1
*/
public void traverseByLevelFromBottom(Node node) {
if (node == null) {
return;
}
List<Node> list = new ArrayList<Node>();
list.add(node);
list.add(new Node(-1)); //-1表示一层结束,打印时要换行
int i = 0;
int size = list.size();
while (i < size) {
Node curNode = list.get(i);

/*交换下面这两个操作,可实现输出:
8 7
6 5 4
3 2
1
*/
if (curNode.getRight() != null) {
list.add(curNode.getRight());
}
if (curNode.getLeft() != null) {
list.add(curNode.getLeft());
}

i++;
if (i == size) {
if (curNode.getData() != -1 && curNode.getLeft() == null && curNode.getRight() == null) { //已经遍历到最底层的最后一个元素,结束循环
break;
}
size = list.size();
list.add(new Node(-1));
}
}

//从后往前遍历,相当于“栈”
for (size = list.size(), i = size - 1; i >=0; i--) {
int val = list.get(i).getData();
if (val == -1) {
System.out.println();
} else {
System.out.print(val + " ");
}
}
}


public Node createTree(int[] data){
List<Node> nodeList=new ArrayList<Node>();
for(int each:data){
Node n=new Node(each);
nodeList.add(n);
}
int lastRootIndex=data.length/2-1;
for(int i=0;i<=lastRootIndex;i++){
Node root=nodeList.get(i);
Node left=nodeList.get(i*2+1);
if(left.getData()!=0){
root.setLeft(left);
}else{
root.setLeft(null);
}
if(i*2+2<data.length){
Node right=nodeList.get(i*2+2);
if(right.getData()!=0){
root.setRight(right);
}else{
root.setRight(null);
}
}

}
Node root=nodeList.get(0);
return root;
}
}

class Node {

int data;
Node left;
Node right;

Node(int data) {
this.data = data;
}

public int getData() {
return data;
}

public void setData(int data) {
this.data = data;
}

public Node getLeft() {
return left;
}

public void setLeft(Node left) {
this.left = left;
}

public Node getRight() {
return right;
}

public void setRight(Node right) {
this.right = right;
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值