feat(tree): Add the array representation of the binary tree(js,ts) (#681)

* fix: fixed the bug of arrToTree function

* feat(tree): Add the array representation of the binary tree(js,ts)

* refactor: Make the arrToTree method match the method in java
pull/688/head
William Yuan 1 year ago committed by GitHub
parent 10c397b172
commit ec82be7dc2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,147 @@
/**
* File: array_binary_tree.js
* Created Time: 2023-08-06
* Author: yuan0221 (yl1452491917@gmail.com)
*/
const { arrToTree } = require('../modules/TreeNode');
const { printTree } = require('../modules/PrintUtil');
/* 数组表示下的二叉树类 */
class ArrayBinaryTree {
#tree;
/* 构造方法 */
constructor(arr) {
this.#tree = arr;
}
/* 节点数量 */
size() {
return this.#tree.length;
}
/* 获取索引为 i 节点的值 */
val(i) {
// 若索引越界,则返回 null ,代表空位
if (i < 0 || i >= this.size()) return null;
return this.#tree[i];
}
/* 获取索引为 i 节点的左子节点的索引 */
left(i) {
return 2 * i + 1;
}
/* 获取索引为 i 节点的右子节点的索引 */
right(i) {
return 2 * i + 2;
}
/* 获取索引为 i 节点的父节点的索引 */
parent(i) {
return (i - 1) / 2;
}
/* 层序遍历 */
levelOrder() {
let res = [];
// 直接遍历数组
for (let i = 0; i < this.size(); i++) {
if (this.val(i) !== null) res.push(this.val(i));
}
return res;
}
/* 深度优先遍历 */
#dfs(i, order, res) {
// 若为空位,则返回
if (this.val(i) === null) return;
// 前序遍历
if (order === 'pre') res.push(this.val(i));
this.#dfs(this.left(i), order, res);
// 中序遍历
if (order === 'in') res.push(this.val(i));
this.#dfs(this.right(i), order, res);
// 后序遍历
if (order === 'post') res.push(this.val(i));
}
/* 前序遍历 */
preOrder() {
const res = [];
this.#dfs(0, 'pre', res);
return res;
}
/* 中序遍历 */
inOrder() {
const res = [];
this.#dfs(0, 'in', res);
return res;
}
/* 后序遍历 */
postOrder() {
const res = [];
this.#dfs(0, 'post', res);
return res;
}
}
/* Driver Code */
// 初始化二叉树
// 这里借助了一个从数组直接生成二叉树的函数
const arr = Array.of(
1,
2,
3,
4,
null,
6,
7,
8,
9,
null,
null,
12,
null,
null,
15
);
const root = arrToTree(arr);
console.log('\n初始化二叉树\n');
console.log('二叉树的数组表示:');
console.log(arr);
console.log('二叉树的链表表示:');
printTree(root);
// 数组表示下的二叉树类
const abt = new ArrayBinaryTree(arr);
// 访问节点
const i = 1;
const l = abt.left(i);
const r = abt.right(i);
const p = abt.parent(i);
console.log('\n当前节点的索引为 ' + i + ' ,值为 ' + abt.val(i));
console.log(
'其左子节点的索引为 ' + l + ' ,值为 ' + (l === null ? 'null' : abt.val(l))
);
console.log(
'其右子节点的索引为 ' + r + ' ,值为 ' + (r === null ? 'null' : abt.val(r))
);
console.log(
'其父节点的索引为 ' + p + ' ,值为 ' + (p === null ? 'null' : abt.val(p))
);
// 遍历树
let res = abt.levelOrder();
console.log('\n层序遍历为' + res);
res = abt.preOrder();
console.log('前序遍历为:' + res);
res = abt.inOrder();
console.log('中序遍历为:' + res);
res = abt.postOrder();
console.log('后序遍历为:' + res);

@ -25,26 +25,13 @@ class TreeNode {
* @param arr * @param arr
* @return * @return
*/ */
function arrToTree(arr) { function arrToTree(arr, i = 0) {
if (arr.length === 0) return null; if (i < 0 || i >= arr.length || arr[i] === null) {
return null;
let root = new TreeNode(arr[0]);
let queue = [root];
let i = 0;
while (queue.length) {
let node = queue.shift();
if (++i >= arr.length) break;
if (arr[i] !== null) {
node.left = new TreeNode(arr[i]);
queue.push(node.left);
}
if (++i >= arr.length) break;
if (arr[i] !== null) {
node.right = new TreeNode(arr[i]);
queue.push(node.right);
}
} }
let root = new TreeNode(arr[i]);
root.left = arrToTree(arr, 2 * i + 1);
root.right = arrToTree(arr, 2 * i + 2);
return root; return root;
} }

@ -0,0 +1,151 @@
/**
* File: array_binary_tree.js
* Created Time: 2023-08-09
* Author: yuan0221 (yl1452491917@gmail.com)
*/
const { arrToTree } = require('../modules/TreeNode');
const { printTree } = require('../modules/PrintUtil');
type Order = 'pre' | 'in' | 'post';
/* 数组表示下的二叉树类 */
class ArrayBinaryTree {
#tree: (number | null)[];
/* 构造方法 */
constructor(arr: (number | null)[]) {
this.#tree = arr;
}
/* 节点数量 */
size(): number {
return this.#tree.length;
}
/* 获取索引为 i 节点的值 */
val(i: number): number | null {
// 若索引越界,则返回 null ,代表空位
if (i < 0 || i >= this.size()) return null;
return this.#tree[i];
}
/* 获取索引为 i 节点的左子节点的索引 */
left(i: number): number {
return 2 * i + 1;
}
/* 获取索引为 i 节点的右子节点的索引 */
right(i: number): number {
return 2 * i + 2;
}
/* 获取索引为 i 节点的父节点的索引 */
parent(i: number): number {
return (i - 1) / 2;
}
/* 层序遍历 */
levelOrder(): number[] {
let res = [];
// 直接遍历数组
for (let i = 0; i < this.size(); i++) {
if (this.val(i) !== null) res.push(this.val(i));
}
return res;
}
/* 深度优先遍历 */
#dfs(i: number, order: Order, res: (number | null)[]): void {
// 若为空位,则返回
if (this.val(i) === null) return;
// 前序遍历
if (order === 'pre') res.push(this.val(i));
this.#dfs(this.left(i), order, res);
// 中序遍历
if (order === 'in') res.push(this.val(i));
this.#dfs(this.right(i), order, res);
// 后序遍历
if (order === 'post') res.push(this.val(i));
}
/* 前序遍历 */
preOrder(): (number | null)[] {
const res = [];
this.#dfs(0, 'pre', res);
return res;
}
/* 中序遍历 */
inOrder(): (number | null)[] {
const res = [];
this.#dfs(0, 'in', res);
return res;
}
/* 后序遍历 */
postOrder(): (number | null)[] {
const res = [];
this.#dfs(0, 'post', res);
return res;
}
}
/* Driver Code */
// 初始化二叉树
// 这里借助了一个从数组直接生成二叉树的函数
const arr = Array.of(
1,
2,
3,
4,
null,
6,
7,
8,
9,
null,
null,
12,
null,
null,
15
);
const root = arrToTree(arr);
console.log('\n初始化二叉树\n');
console.log('二叉树的数组表示:');
console.log(arr);
console.log('二叉树的链表表示:');
printTree(root);
// 数组表示下的二叉树类
const abt = new ArrayBinaryTree(arr);
// 访问节点
const i = 1;
const l = abt.left(i);
const r = abt.right(i);
const p = abt.parent(i);
console.log('\n当前节点的索引为 ' + i + ' ,值为 ' + abt.val(i));
console.log(
'其左子节点的索引为 ' + l + ' ,值为 ' + (l === null ? 'null' : abt.val(l))
);
console.log(
'其右子节点的索引为 ' + r + ' ,值为 ' + (r === null ? 'null' : abt.val(r))
);
console.log(
'其父节点的索引为 ' + p + ' ,值为 ' + (p === null ? 'null' : abt.val(p))
);
// 遍历树
let res = abt.levelOrder();
console.log('\n层序遍历为' + res);
res = abt.preOrder();
console.log('前序遍历为:' + res);
res = abt.inOrder();
console.log('中序遍历为:' + res);
res = abt.postOrder();
console.log('后序遍历为:' + res);
export {};

@ -30,27 +30,13 @@ class TreeNode {
* @param arr * @param arr
* @return * @return
*/ */
function arrToTree(arr: (number | null)[]): TreeNode | null { function arrToTree(arr: (number | null)[], i: number = 0): TreeNode | null {
if (arr.length === 0) { if (i < 0 || i >= arr.length || arr[i] === null) {
return null; return null;
} }
let root = new TreeNode(arr[i]);
const root = new TreeNode(arr[0] as number); root.left = arrToTree(arr, 2 * i + 1);
const queue = [root]; root.right = arrToTree(arr, 2 * i + 2);
let i = 0;
while (queue.length) {
const node = queue.shift() as TreeNode;
if (++i >= arr.length) break;
if (arr[i] !== null) {
node.left = new TreeNode(arr[i] as number);
queue.push(node.left);
}
if (++i >= arr.length) break;
if (arr[i] !== null) {
node.right = new TreeNode(arr[i] as number);
queue.push(node.right);
}
}
return root; return root;
} }

Loading…
Cancel
Save