递归树
代码:
public static void f(Node head) {
// 回到父节点再进行判断
if(head == null) {
return;
}
// 回到父节点再访问左节点
f(head.left);
// 回到父节点再访问右节点
f(head.right);
// 执行完再回到父节点
}
例子:(递归序)
先序遍历(先中后都是在递归树的基础上遍历的)
先序:头左右
非递归实现步骤:
- 每次从栈中弹出一个节点cur
- 打印cur
- 先右再左(没有就什么也不做,继续弹出)
- 循环
public static void preOrderUnRecur(Node head) {
if(head != null){
Stack<Node> stack = new Stack<Node>();
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);
}
}
}
}
中序遍历
中序:左头右
非递归实现步骤: 每颗子树整棵树左边界进栈,依次弹出的过程中,打印,对弹出节点右树循环。(看弹出节点的右树有没有,有的话,进栈,这个节点左边界进展)
public static void inOrderUnRecur(Node Head){
if(head != null) {
Stack<Node> stack = new Stack<Node>(); // 创建栈
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();
}
步骤图:
后序遍历
后序:左右头 非递归实现步骤:
- 弹cur
- 当前节点cur放到收集栈
- 先左再右
- 循环
public static void posOrderUnRecur1(Node head) {
if(head != null){
Stack<Node> s1 = new Stack<Node>();
Stack<Node> s2 = new Stack<Node>(); // 收集栈
s1.push(head);
while(!s1.isEmpty()){
head = s1.pop(); // 弹出
s2.push(head); // 当前节点cur放到收集栈
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 static void w (Node head) {
if(head == null){
return;
}
Queue<Node> queue = new linkedList<>(); // 创建队列
queue.add(head);
while(!queue.isEmpty()) {
Node cur = queue.poll(); // 队列弹出的值
System.out.println(cur.value);
if(cur.left != null) {
queue.add(cur.left); // 左节点进队列
}
if(cur.right != null) {
queue.add(cur.right); // 右节点进队列
}
}
}
步骤图:
二叉树最大宽度
public static void w (Node head) {
if(head == null){
return;
}
Queue<Node> queue = new linkedList<>(); // 创建队列
queue.add(head);
HashMap<Node, Integer> levelMap = new HashMap(); // 创建哈希表
levelMap.push(head, 1); // 当前节点 节点所在的层数
int curLevel = 1; // 当前层数
int curLevelNodes = 0; // 当前层数节点数
int max = Integer.MIN_VALUE; // 某一层的节点最多 多少个
while(!queue.isEmpty()) {
Node cur = queue.poll(); // 队列弹出的值
int curNodeLevel = levelMap.get(cur); // 当前节点所在的层数
if(curNodeLevel = curLevel) { // 弹出节点所在的层数还在我要计算的层数
curLevelNodes++; // 节点数++
} else { // 下一层了
max = Math.max(max, curLevelNodes)
curLevel++;
curLevelNodes = 1;
}
if(cur.left != null) {
levelMap.put(cur.left, curNodeLevel+1); // 进栈时,记录节点所在的层数
queue.add(cur.left); // 左节点进队列
}
if(cur.right != null) {
levelMap.put(cur.right, curNodeLevel+1); // 进栈时,记录节点所在的层数
queue.add(cur.right); // 右节点进队列
}
}
}
判断二叉树是搜索二叉树
递归写法:
public static int preValue = Integer.MIN_VALUE;
public static boolean checkBST(Node head) {
if(head == null) {
return true;
}
boolean isLeftBst = checkBST(head.left); // 判断左子树是不是搜索二叉树
if(!isLeftBst) {
return false;
}
if(head.value <= preValue) {
return false;
} else {
preValue = head.value;
}
return checkBST(head.right);
}
非递归写法:(中序遍历)
public static boolean checkBST3(Node head) {
if(head != null){
int preValue = Integer.MIN_VALUE;
Stack<Node> stack = new Stack<Node>();
while(!stack.isEmpty() || head != null) {
if(head != null){
stack.push(head);
head = head.left;
} else {
head = stack.pop();
// 新增搜索二叉树的判断条件(代码原来是中序遍历)
if(head.value <= preValue){
return false;
} else {
preValue = head.value;
}
head = head.right;
}
}
}
return true;
}
判断二叉树是完全二叉树
- 任意节点,有右孩子没有左孩子,返回false
- 在第一个条件不违规的情况下,如果遇到了第一个左右孩子不全的情况下,后续的所有节点必须是叶节点
public static boolean isCBT(Node head) {
if(head == null){
return true;
}
LinkedList<Node> queue = new LinkedList<>(); // 创建队列
// 是否遇到过左右两个孩子不双全的节点
boolean leaf = false;
Node l = null;
Node r = null;
queue.add(head);
while(!queue.isEmpty()){
head = queue.poll();
l = head.left;
r = head.right;
if(
// 左右两个孩子不双全 && 不是叶节点(又发现当前节点有孩子)
(leaf && (l != null || r != null))
||
(l == null && r != null)
) {
return false;
}
if(l != null){
queue.add(l);
}
if(r != null){
queue.add(r);
}
if(l == null || r == null) {
leaf = true;
}
}
return true;
}
反转二叉树
初始数据
let list = {
id: "4",
left: {
id: "2",
left: {
id: "1",
left: null,
right: null,
},
right: {
id: "3",
left: null,
right: null,
},
},
right: {
id: "7",
left: {
id: "6",
left: null,
right: null,
},
right: {
id: "9",
left: null,
right: null,
},
},
};
定义一个临时的变量tmp,用于交换 left 和 right 递归处理 left和right,,如果传递的值是null停止处理
function reverseBTree(node) {
if (!node) {
return;
}
let tmp = node.left;
node.left = node.right;
node.right = tmp;
reverseBTree(node.left);
reverseBTree(node.right);
}