diff --git a/codes/javascript/chapter_tree/array_binary_tree.js b/codes/javascript/chapter_tree/array_binary_tree.js new file mode 100644 index 000000000..e5a5a6003 --- /dev/null +++ b/codes/javascript/chapter_tree/array_binary_tree.js @@ -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); diff --git a/codes/javascript/modules/TreeNode.js b/codes/javascript/modules/TreeNode.js index d879ef51c..bdde3519d 100644 --- a/codes/javascript/modules/TreeNode.js +++ b/codes/javascript/modules/TreeNode.js @@ -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; } diff --git a/codes/typescript/chapter_tree/array_binary_tree.ts b/codes/typescript/chapter_tree/array_binary_tree.ts new file mode 100644 index 000000000..3687bc541 --- /dev/null +++ b/codes/typescript/chapter_tree/array_binary_tree.ts @@ -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 {}; diff --git a/codes/typescript/modules/TreeNode.ts b/codes/typescript/modules/TreeNode.ts index 275189e77..e91232db0 100644 --- a/codes/typescript/modules/TreeNode.ts +++ b/codes/typescript/modules/TreeNode.ts @@ -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; }