二叉树
一、概念及结构
一棵二叉树是结点的一个有限集合,该集合或者为空,或者是由一个根节点加上两棵别称为左子树和右子树的二叉树组成。
二叉树的特点:
1、每个结点最多有两棵子树,即二叉树不存在度大于2的结点。
2、二叉树的子树有左右之分,其子树的次序不能颠倒。
结构:
class Node {
V value;
Node left;
Node right;
}
二、二叉树三种遍历方法
1、定义
2、举例
假设一个二叉树如图:
先序遍历(头左右):1245367
中序遍历(左头右):4251637
后序遍历(左右头):4526731
3、代码(递归方法)
//前序遍历
public static void pre(Node head) {
if(head==null) {
return;
}
System.out.print(head.value+" ");
pre(head.left);
pre(head.right);
}
//中序遍历
public static void in(Node head) {
if(head==null) {
return;
}
in(head.left);
System.out.print(head.value+" ");
in(head.right);
}
//后序遍历
public static void pos(Node head) {
if(head==null) {
return;
}
pos(head.left);
pos(head.right);
System.out.print(head.value+" ");
}
4.原理解析
假设有个递归函数:
public static void f(Node head) {
if(head==null) {
return;
}
//1
f(head.left);
//2
f(head.right);
//3
}
//1:第一次来到节点
//2:第二次来到节点
//3:第三次来到节点
对于上述的二叉树有这么一个递归序:
通过观察我们发现,先序遍历是第一次访问节点时对该节点的操作,中序遍历是第二次访问节点时对该节点的操作,后序遍历是第三次访问节点时对该节点的操作。
5.非递归方法
非递归方法需要用到栈。
我们直接上代码:
//先序遍历(非递归)
public static void pre(Node head) {
if(head==null) {
return;
}
Stack<Node> stack=new Stack<>();
stack.push(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);
}
}
}
//中序遍历(非递归)
public static void in(Node head) {
if(head==null) {
return;
}
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;
}
}
}
//后序遍历(非递归)
public static void pos(Node head) {
if(head==null) {
return;
}
Stack<Node> stack=new Stack<>();
stack.push(head);
Node h=head;
Node c=null;
while(!stack.isEmpty()) {
c=stack.peek();
if(c.left!=null&&h!=c.right&&h!=c.left) { //h!=c.right连右节点都遍历了,左节点肯定遍历了
stack.push(c.left);
}else if(c.right!=null&&h!=c.right) {
stack.push(c.right);
}else {
System.out.print(stack.pop().value+" ");
h=c;
}
}
}
三、二叉树的层序遍历
层序遍历即把二叉树从上到下按每层的顺序,从左往右遍历。
这里需要用到队列。
代码如下:
public static void level(Node head) {
if(head==null) {
return;
}
Queue<Node> queue=new LinkedList<>();
queue.offer(head);
while(!queue.isEmpty()) {
int curNum=queue.size(); //此时队列中只存了当前层的节点
for(int i=0;i<curNum;i++) {
Node curNode=queue.poll();
if(curNode.left!=null) {
queue.offer(curNode.left);
}
if(curNode.right!=null) {
queue.offer(curNode.right);
}
}
}
}
四、总结
我在刚接触函数递归的时候懵懵懂懂,当深入学习二叉树时才明白递归的套路。
三种遍历方式是以后学习树形dp的基础,因此务必将这三种递归套路熟悉。
参考博文:https://blog.csdn.net/weixin_45796387/article/details/114994648