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
|
* @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;
|
let root = new TreeNode(arr[i]);
|
||||||
if (arr[i] !== null) {
|
root.left = arrToTree(arr, 2 * i + 1);
|
||||||
node.right = new TreeNode(arr[i]);
|
root.right = arrToTree(arr, 2 * i + 2);
|
||||||
queue.push(node.right);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return root;
|
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
|
* @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…
x
Reference in New Issue
Block a user