(1)先序递归遍历(LeetCode144)
public static void preOrderRecur(Node head) {
if (head == null) {
return;
}
System.out.print(head.value + " ");
preOrderRecur(head.left);
preOrderRecur(head.right);
}
(2)中序递归遍历(LeetCode94)
public static void inOrderRecur(Node head) {
if (head == null) {
return;
}
inOrderRecur(head.left);
System.out.print(head.value + " ");
inOrderRecur(head.right);
}
(3)后序递归遍历(LeetCode145)
public static void posOrderRecur(Node head) {
if (head == null) {
return;
}
posOrderRecur(head.left);
posOrderRecur(head.right);
System.out.print(head.value + " ");
}
(1)二叉树的先序非递归遍历
代码思想:利用栈结构,先打印中间节点,再将右孩子、左孩子压入栈,栈逆序打印,实现中左右的打印顺序。
代码实现:
public static void preOrderUnRecur(Node head) {
System.out.print("pre-order: ");
if (head != null) {
Stack 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();
}
(2)二叉树的中序非递归遍历
代码思想:
代码实现:
public static void inOrderUnRecur(Node head) {
System.out.print("in-order: ");
if (head != null) {
Stack 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();
}
(3)二叉树的后序非递归遍历
代码思想:后序遍历的顺序是左右中。在栈中,逆序就是中右左,这与先序遍历很类似,只不过先序是中左右,所以我们只需要将先序的先压右孩子再压左孩子,改为先压左孩子再压右孩子,同时我们利用第二个栈实现逆序。
代码实现:
public static void posOrderUnRecur1(Node head) {
System.out.print("pos-order: ");
if (head != null) {
Stack s1 = new Stack();
Stack 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();
}
对付层次遍历最好的工具就是对列,每一层的节点顺序进入对列并从前到后打印。只不过需要区别哪些节点对待哪一层。
代码实现:
public List> levelOrder(TreeNode root) {
List> levels = new ArrayList<>();
if (root == null) {
return levels;
}
Queue queue = new LinkedList<>();
queue.add(root);
int level = 0;
while (!queue.isEmpty()) {
levels.add(new ArrayList<>());
int level_length = queue.size();
for (int i = 0; i < level_length; i++) {
TreeNode node = queue.remove();
levels.get(level).add(node.val);
if (node.left != null) queue.add(node.left);
if (node.right != null) queue.add(node.right);
}
level++;
}
return levels;
}
拓展题目:之字形打印二叉树
代码思想:除了对列之外,需要使用栈空间,因为对列无法实现全部之字形的打印,而实际上,二叉树行数从0开始计数,奇数行使用栈打印,偶数行使用对列打印。
代码实现:
public ArrayList > Print(TreeNode pRoot) {
ArrayList> res = new ArrayList<>();
if (pRoot == null) {
return res;
}
Queue queue = new LinkedList<>();
Stack stack = new Stack<>();
queue.add(pRoot);
int level = 0;
res.add(new ArrayList());
res.get(level++).add(pRoot.val);
while (!queue.isEmpty()) {
res.add(new ArrayList<>());
int size = queue.size();
for (int i = 0; i < size; i++) {
TreeNode head = queue.remove();
if (head.left != null) {
queue.offer(head.left);
if (level % 2 == 0) { //偶数选择队列
res.get(level).add(head.left.val);
}
if (level % 2 != 0) {
stack.push(head.left);
}
}
if (head.right != null) {
queue.offer(head.right);
if (level % 2 == 0) { //偶数选择队列
res.get(level).add(head.right.val);
}
if (level % 2 != 0) {
stack.push(head.right);
}
}
}
/*奇数选择栈*/
while (level % 2 != 0 && !stack.isEmpty()) {
res.get(level).add(stack.pop().val);
}
level++;
}
res.remove(res.size()-1);
return res;
}
这里的宽度遍历是指找出二叉树中宽度最大的一层节点数。每一层的宽度被定义为两个端点(该层最左和最右的非空节点,两端点间的null
节点也计入长度)之间的长度。
代码思想:我们只需要在层次遍历的基础上加以改进,即记录当前节点的位置信息,设当前节点位置序号为pos,则它的左孩子序号为pos*2,右孩子序号为pos*2+1,用一个list辅助空间记录位置信息,在每一层遍历后比较位置区间,取最大值。
代码实现:
public int widthOfBinaryTree(TreeNode root) {
LinkedList list = new LinkedList<>();
if (root == null) {
return 0;
}
Queue queue = new LinkedList<>();
queue.offer(root);
list.add(1); //把根节点的序号存储
int res = 1;
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i = 2) {
res = Math.max(res, list.getLast() - list.getFirst() + 1);
}
}
return res;
}
二叉树的最大深度,即取从根节点到最远叶子节点的最长路径上的节点数,利用递归解决即可。
代码实现:
public int maxDepth(TreeNode root) {
if (root == null) return 0;
int left = maxDepth(root.left);
int right = maxDepth(root.right);
return Math.max(left, right) + 1;
}