标签:-o 现在 his toc tle 数组 int set 思考
之前为了求快,认为递归和动态规划是一类的,导致做了不少递归的题只能想到思路,但就是没法代码实现出来!!!
现在学习二叉树,我觉得对学习递归真的很有帮助!
二叉树遍历是基础,如果我们不能遍历二叉树,又如何对二叉树的节点进行操作呢?
二叉树的节点:
/**
* @author keboom
* @date 2021/4/30
*/
public class Node {
public int value;
public Node left;
public Node right;
public Node(int data) {
this.value = data;
}
/**
* 10
* 12 15
* 4 7 5 18
* @return
*/
public static Node getTestTree() {
Node node10 = new Node(10);
Node node5 = new Node(5);
Node node15 = new Node(15);
Node node4 = new Node(4);
Node node7 = new Node(7);
Node node12 = new Node(12);
Node node18 = new Node(18);
node10.left = node12;
node10.right = node15;
node12.left = node4;
node12.right = node7;
node15.left = node5;
node15.right = node18;
return node10;
}
}
getTestTree
此方法为了方便测试,不用理会。
public void preOrderRecur(Node head) {
if (head == null) {
return;
}
System.out.println(head.value + " ");
preOrderRecur(head.left);
preOrderRecur(head.right);
}
public void inOrderRecur(Node head) {
if (head == null) {
return;
}
inOrderRecur(head.left);
System.out.println(head.value + " ");
inOrderRecur(head.right);
}
public void posOrderRecur(Node head) {
if (head == null) {
return;
}
posOrderRecur(head.left);
posOrderRecur(head.right);
System.out.println(head.value + " ");
}
以上分别为先序,中序和后序遍历。
我认为这三种遍历的区别:
先序遍历:先打印,再向下递归
中序和后序:先递归到最下面,再打印
只看简单的遍历太简单不直观,请看下面的几道题
接下里的几道题目在求解过程中我会跟二叉树的遍历做一些联系,我认为做这些联系是有助于解题的??
public void preOrderUnRecur(Node head) {
System.out.println("pre-order: ");
if (head != null) {
Stack<Node> stack = new Stack<>();
stack.add(head);
while (!stack.isEmpty()) {
head = stack.pop();
System.out.print(head.value + " ");
if (head.right != null) {
stack.push(head.right);
}
if (head.left != null) {
stack.push(head.left);
}
}
}
System.out.println();
}
public void inOrderUnRecur(Node head) {
System.out.println("in-order: ");
if (head != null) {
Stack<Node> stack = new Stack<>();
while (!stack.isEmpty() || head != null) {
if (head != null) {
stack.push(head);
head = head.left;
} else {
head = stack.pop();
System.out.print(head.value + " ");
head = head.right;
}
}
}
System.out.println();
}
/**
* 先将头放入s2,然后将右子树放入s2,最后将左子树放入s2
*/
public void posOrderUnRecur1(Node head) {
System.out.println("pos-order: ");
if (head != null) {
Stack<Node> s1 = new Stack<>();
Stack<Node> s2 = new Stack<>();
s1.push(head);
while (!s1.isEmpty()) {
head = s1.pop();
s2.push(head);
if (head.left != null) {
s1.push(head.left);
}
if (head.right != null) {
s1.push(head.right);
}
}
while (!s2.isEmpty()) {
System.out.print(s2.pop().value + " ");
}
}
System.out.println();
}
递归的前中后序遍历看起来挺有规律,但是非递归的就不太一样了,我是找不到啥规律。
非递归的前序遍历和中序遍历都模拟了递归调用栈。
给定一棵二叉树的头节点 head,按照标准实现二叉树的边界节点的逆时针打印。
1.头节点为边界节点。
2.叶节点为边界节点。
3.如果节点在其所在的层中是最左的或最右的,那么该节点也是边界节点。
打印结果为:1,2,4,7,11,13,14,15,16,12,10,6,3
Node[][] edgeMap = new Node[height][2]
,edgeMap
是存储二叉树每一层的最左和最右的边缘节点edgeMap
后便可以打印左边缘节点二叉树遍历是基础,以下代码我会跟二叉树的前中后序遍历做一些联系,如果读者觉着这样的联系并不好,那就忽略吧。
/**
* 获得二叉树的高度
* 通过不断向下递归查找,找到最大高度
* @param head
* @param height
* @return
*/
private int getHeight(Node head, int height) {
if (head == null) {
return height;
}
return Math.max(getHeight(head.left, height + 1), getHeight(head.right, height + 1));
}
此方法我认为类似后序遍历。向左右递归,得到左右的树高,然后在做比较取大一点的。
符合先左右递归,然后操作。
edgeMap
/**
* edgeMap是一个二维数组,记录树的每一层最左和最右边缘节点。
* @param h
* @param l
* @param edgeMap
*/
private void setEdgeMap(Node h, int l, Node[][] edgeMap) {
if (h == null) {
return;
}
edgeMap[l][0] = edgeMap[l][0] == null ? h : edgeMap[l][0];
edgeMap[l][1] = h;
setEdgeMap(h.left, l + 1, edgeMap);
setEdgeMap(h.right, l + 1, edgeMap);
}
这个一看就符合先序遍历。
先操作edgeMap
,然后递归。
edgeMap[l][0] = edgeMap[l][0] == null ? h : edgeMap[l][0];
edgeMap[l][1] = h;
上面两行代码挺巧妙的,仔细思考先序遍历的过程和规律,发现这两行代码正好就能求的左右边缘。
/**
* 打印不是边缘节点的叶节点
* @param h
* @param l
* @param m
*/
private void printLeafNotInMap(Node h, int l, Node[][] m) {
if (h == null) {
return;
}
// 首先要是叶子结点,并且不是左右边缘
if (h.left == null && h.right == null && h != m[l][0] && h != m[l][1]) {
System.out.print(h.value + " ");
}
printLeafNotInMap(h.left, l + 1, m);
printLeafNotInMap(h.right, l + 1, m);
}
这个也是先序遍历了。
符合先操作,后递归。
先序遍历每个节点,判断其是叶结点但不为边缘节点。
/**
* @param head
*/
public void printEdge1(Node head) {
if (head == null) {
return;
}
int height = getHeight(head, 0);
Node[][] edgeMap = new Node[height][2];
setEdgeMap(head, 0, edgeMap);
for (int i = 0; i != edgeMap.length; i++) {
System.out.print(edgeMap[i][0].value + " ");
}
printLeafNotInMap(head, 0, edgeMap);
for (int i = edgeMap.length - 1; i != -1; i--) {
if (edgeMap[i][0] != edgeMap[i][1]) {
System.out.print(edgeMap[i][1].value + " ");
}
}
System.out.println();
}
主方法与思路一致,不多说了。
完整代码:Gitee
(未完待续....)????
标签:-o 现在 his toc tle 数组 int set 思考
原文地址:https://www.cnblogs.com/keboom/p/14780452.html