🥳每日一练-统计二叉树节点的数量-JS简易版

今天分享的内容是如何统计一个排序二叉树节点的数量。

具体的需求是这样的:一个普通的排序二叉树,现在需要在每个节点都加一个 count 属性,表示以该节点为根的子树下面所拥有节点的数量。

如上图,1 节点的 count 为 0,2 节点的 count 为 2,4 节点的 count 为 5 等等

问题很清晰,解决起来不难。具体思路是先计算叶子节点的 count,然后依次往上计算父节点的 count,知道计算完 rootcount 就结束。

不是排序二叉树,也可以。但看到的算法题目就是这么要求的🐒

准备数据

javascript 复制代码
const data = [9, 4, 5, 3, 2, 7, 8, 95, 33, 22];

const generator = (data) => {
	const insert = (tree, value) => {
		if (!tree) return { value, left: null, right: null};
		if (value < tree.value) {
			tree.left = insert(tree.left, value);
		} else {
			tree.right = insert(tree.right, value);
		}
		return tree;
	};
  
	let tree = null;
	data.forEach((item) => {
		tree = insert(tree, item);
	});
	return tree;
};

const tree = generator(data);

上面代码用generator 函数将 data 数组转成了一个排序二叉树 tree。将 tree 打印出来是这个样子:

以 9 节点为根节点的二叉树。打印的深度为叶子节点下一层,左右子树为空的话,就打印 null。

对二叉树打印感兴趣的话,可以看下面这个代码:

javascript 复制代码
let res = "";

const printTree1 = (data, deeps = [1]) => {
	let space = deeps
		.slice(0, -1)
		.map((item) => {
			return item == 1 ? "|\t\t" : "\t\t";
		})
		.join("");

	space += "|__";
	const content = data ? data.value : null;
	res = res + space + content + "\n";
	
  if (!data) return;
	printTree1(data.left, [...deeps, 1]);
	printTree1(data.right, [...deeps, 0]);

	return res;
};

这个代码不是重点,就不讲解了

整理节点数量

先子节点,后父节点,这是典型的后序遍历啊。那就先复习一遍后序遍历吧

javascript 复制代码
const printTree = (tree) => {
	if (!tree) return null;
	printTree(tree.left);
	printTree(tree.right);
	console.log(tree.value);
};

printTree(tree);
// 2
// 3
// 8
// 7
// 5
// 4
// 22
// 33
// 95
// 9

这是一个简单直观的后序遍历函数。先左子树,后右子树,再根节点。我们可以在函数最后一行的输出做文章,将其修改为可以统计节点数量的功能

javascript 复制代码
const calculateNodeCount = (node) => {
	if (!node) return;
	node.count = (node.left?.count || 0) + (node.right?.count || 0);
	if (node.left) node.count++;
	if (node.right) node.count++;
};

const collectCount = (tree) => {
	if (!tree) return null;
	collectCount(tree.left);
	collectCount(tree.right);
  //calculate Node Count
  calculateNodeCount(tree);
  
	console.log(tree.value + "," + tree.count);
};

collectCount(tree);
// 2,0
// 3,1
// 8,0
// 7,1
// 5,2
// 4,5
// 22,0
// 33,1
// 95,2
// 9,9

输出的结果,前面是节点的值,后面是节点的 count。大家可以和上面打印出来的二叉树树形结构对比,看看 count 值是否正确

逻辑很简单,先计算左子树的 count,然后计算右子树的 count,在统计根的 count

很简单吧

懂得了计算思路,然后就是直接套用二叉树的遍历模版就可以了。其实关于二叉树的很多问题都是这样,只要你明白了如何遍历,你就能解决问题。甚至是后面将会学习的图的 DFS(深度优先遍历),BFS(广度优先遍历),这些都是基于树的遍历算法上。而 Dijkstra,prim,kruskal,floyd 算法等等,都是基于图的 DFS 和 BFS。所以二叉树的遍历是基础,是掌握复杂数据结构的基石

非递归版本

懂得了递归版本,非递归版本怎么写呢?还是和上面一样,直接套用后序遍历的代码模版即可

javascript 复制代码
const collectCount2 = (tree) => {
	const stack = [];
	let node = tree,
		pre = null;
	while (node || stack.length !== 0) {
		while (node) {
			stack.push(node);
			node = node.left;
		}
		const currentNode = stack.slice(-1)[0];
		if (currentNode.right == null || pre == currentNode.right) {
			//calculate node count
			calculateNodeCount(currentNode);
      console.log(currentNode.value + "," + currentNode.count);
			pre = currentNode;
			stack.pop();
		} else {
			node = currentNode.right;
		}
	}
};

collectCount2(tree);
// 2,0
// 3,1
// 8,0
// 7,1
// 5,2
// 4,5
// 22,0
// 33,1
// 95,2
// 9,9

输出的结果,前面是节点的值,后面是节点的 count。大家可以和上面打印出来的二叉树树形结构对比,看看 count 值是否正确

代码就是简单的二叉树后序遍历的非递归代码,不解释了。想看详细解释的,可以看这篇文章:🥳每日一练-二叉树后序的遍历-JS简易版 - 掘金

总结:

这篇文章分享了如何整理二叉树节点的数量。文中提供了两种解决办法,一种是递归版本,另一种非递归版本。问题不难,理解了解题思路,代码部分就是套用二叉树的遍历模版了

你觉得这篇文章怎么样?我每天都会分享一篇算法小练习,喜欢就点赞+关注吧

相关推荐
Dread_lxy16 分钟前
vue 依赖注入(Provide、Inject )和混入(mixins)
前端·javascript·vue.js
ChoSeitaku20 分钟前
链表循环及差集相关算法题|判断循环双链表是否对称|两循环单链表合并成循环链表|使双向循环链表有序|单循环链表改双向循环链表|两链表的差集(C)
c语言·算法·链表
Fuxiao___28 分钟前
不使用递归的决策树生成算法
算法
我爱工作&工作love我33 分钟前
1435:【例题3】曲线 一本通 代替三分
c++·算法
白-胖-子1 小时前
【蓝桥等考C++真题】蓝桥杯等级考试C++组第13级L13真题原题(含答案)-统计数字
开发语言·c++·算法·蓝桥杯·等考·13级
workflower1 小时前
数据结构练习题和答案
数据结构·算法·链表·线性回归
奔跑草-1 小时前
【前端】深入浅出 - TypeScript 的详细讲解
前端·javascript·react.js·typescript
好睡凯1 小时前
c++写一个死锁并且自己解锁
开发语言·c++·算法
Sunyanhui11 小时前
力扣 二叉树的直径-543
算法·leetcode·职场和发展
羡与1 小时前
echarts-gl 3D柱状图配置
前端·javascript·echarts