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
This commit is contained in:
parent
10c397b172
commit
ec82be7dc2
147
codes/javascript/chapter_tree/array_binary_tree.js
Normal file
147
codes/javascript/chapter_tree/array_binary_tree.js
Normal file
@ -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
|
||||
* @return
|
||||
*/
|
||||
function arrToTree(arr) {
|
||||
if (arr.length === 0) 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);
|
||||
}
|
||||
function arrToTree(arr, i = 0) {
|
||||
if (i < 0 || i >= arr.length || arr[i] === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let root = new TreeNode(arr[i]);
|
||||
root.left = arrToTree(arr, 2 * i + 1);
|
||||
root.right = arrToTree(arr, 2 * i + 2);
|
||||
return root;
|
||||
}
|
||||
|
||||
|
151
codes/typescript/chapter_tree/array_binary_tree.ts
Normal file
151
codes/typescript/chapter_tree/array_binary_tree.ts
Normal file
@ -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
|
||||
* @return
|
||||
*/
|
||||
function arrToTree(arr: (number | null)[]): TreeNode | null {
|
||||
if (arr.length === 0) {
|
||||
function arrToTree(arr: (number | null)[], i: number = 0): TreeNode | null {
|
||||
if (i < 0 || i >= arr.length || arr[i] === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const root = new TreeNode(arr[0] as number);
|
||||
const queue = [root];
|
||||
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);
|
||||
}
|
||||
}
|
||||
let root = new TreeNode(arr[i]);
|
||||
root.left = arrToTree(arr, 2 * i + 1);
|
||||
root.right = arrToTree(arr, 2 * i + 2);
|
||||
return root;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user