题目:打印二叉树的边界节点(注:片文全部来自左神写得书,见文末注解)
给定一颗二叉树的头结点head,按照如下两种标准分别实现二叉树边界点的逆时针打印
标准一:
1、头结点为边界节点
2、叶节点为边界节点
3、如果节点在其所在的层中是最左或是最右的,那么也是边界节点
标准二:
1、头结点为边界节点
2、叶节点为边界节点
3、树左边界延伸下去的路径为边界节点
4、树右边界延伸下去的路径为边界节点
下面借鉴了左神讲述的内容进行模拟了一下,具体过程,左神推敲如下(我也是直接搬的左神的思路,注明):
标准一:
1、得到二叉树每一层上最左边和最右边的节点
2、从上到下打印所有层中的最左节点
3、先序遍历二叉树,打印那些不属于某一层最左或最右的节点
4、从上到下打印所有层中的最右节点
标准二:
1、从头节点开始往下寻找,只要找到第一个既有左孩子又有右孩子的节点,直接进入步骤2
,记为h。在这个过程中,找过的节点直接打印。
2、h的左子树先进入步骤3的打印过程;h的右子树再进入步骤4的打印过程,最后返回
3、打印左边界的延伸路径以及h左子树上所有的叶节点
4、打印右边界的延伸路径以及h右子树上所有的叶节点
按照标准1打印:1,2,4,7,11,13,14,15,16,12,10,6,3
按照标准2打印: 1,2,4,7,13,14,15,16,10,6,3
java代码实现如下
package com.gcp.www;
/**
* 标准1
* 头结点为边界节点
* 叶节点为边界节点
* 如果节点在其所在的层中是最左还是最右,那么也是节点
* @author chaplinJ
*标准2
*头结点为边界节点
*叶节点为边界节点
*树左边界延伸下去的路径为边界节点
*树右边界延伸下去的路径是边界节点
*/
class Node{
public int value;
public Node left;
public Node right;
public Node(int data){
this.value = data;
}
}
public class PrintBinaryTreeBoundary {
/**
* 按照标准1打印二叉树边界节点
* @param head
*/
public void printBitTree1(Node head){ //按照标准1打印二叉树的边界节点
if(head == null){
return;
}
int height = getHeight(head,0); //获取树的高度
Node[][] edgeTo = new Node[height][2];
setEdgeMap(head, 0, edgeTo);
//打印做边界节点
for(int i = 0 ; i < edgeTo.length;i++){
System.out.print(edgeTo[i][0].value + " ");
}
//打印叶子节点
printLeafNotInMap(head,0,edgeTo);
//打印右节点但不是做节点的
for(int i = height - 1; i >=0;i--){
if(edgeTo[i][0] != edgeTo[i][1]){
System.out.print(edgeTo[i][1].value + " ");
}
}
}
/**
* 按照标准2打印二叉树的边界节点
* @param head
*/
public void printBitTree2(Node head){ //按照标准2打印二叉树的边界节点
if(head == null){
return;
}
System.out.print(head.value + " ");
if(head.left != null && head.right != null){ //
printLeftEdge(head.left,true);
printRightEdge(head.right, true);
}else{
printBitTree2(head.left != null?head.left : head.right);
}
System.out.println();
}
public void printLeftEdge(Node h,boolean print){
if(h == null){
return;
}
if(print || (h.left == null && h.right == null)){
System.out.print(h.value + " ");
}
printLeftEdge(h.left, print);
printLeftEdge(h.right, print && h.left == null ? true:false);
}
public void printRightEdge(Node h,boolean print){
if(h == null){
return;
}
printRightEdge(h.left, print && h.right == null?true:false);
printRightEdge(h.right, print);
if(print || (h.left == null && h.right == null)){
System.out.print(h.value +" ");
}
}
private void setEdgeMap(Node head,int l,Node[][] edgeTo){
if(head == null){
return;
}
edgeTo[l][0] = (edgeTo[l][0] == null?head:edgeTo[l][0]);
edgeTo[l][1] = head;
setEdgeMap(head.left,l+1,edgeTo);
setEdgeMap(head.right,l+1,edgeTo);
}
private void printLeafNotInMap(Node head,int l,Node[][] edgeTo){
if(head == null){
return;
}
if(head.left == null && head.right == null && edgeTo[l][0] != head && head!= edgeTo[l][1]){
System.out.print(head.value + " ");
}
printLeafNotInMap(head.left, l+1, edgeTo);
printLeafNotInMap(head.right, l+1, edgeTo);
}
/**
* 获取树的高度
* @param head
* @param l
* @return
*/
private int getHeight(Node head,int l){
if(head == null){
return l;
}else
return Math.max(getHeight(head.left,l+1), getHeight(head.right,l + 1));
}
public static void main(String[] args) {
Node node1 = new Node(1);
Node node2 = new Node(2);
Node node3 = new Node(3);
Node node4 = new Node(4);
Node node5 = new Node(5);
Node node6 = new Node(6);
Node node7 = new Node(7);
Node node8 = new Node(8);
Node node9 = new Node(9);
Node node10 = new Node(10);
Node node11 = new Node(11);
Node node12 = new Node(12);
Node node13 = new Node(13);
Node node14 = new Node(14);
Node node15 = new Node(15);
Node node16 = new Node(16);
node1.right = node3;
node1.left = node2;
node2.right = node4;
node4.left = node7;
node4.right = node8;
node8.right = node11;
node11.left = node13;
node11.right = node14;
node3.left = node5;
node3.right = node6;
node5.left = node9;
node5.right = node10;
node9.left = node12;
node12.left = node15;
node12.right = node16;
new PrintBinaryTreeBoundary().printBitTree1(node1);
System.out.println();
new PrintBinaryTreeBoundary().printBitTree2(node1);
}
}
注:文章算法内容来自做左程云—IT名企算法与数据结构题目最优解