Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add JavaScript codes for Tree #71

Merged
merged 4 commits into from
Dec 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 146 additions & 0 deletions codes/javascript/chapter_tree/binary_search_tree.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/**
* File: binary_tree.js
* Created Time: 2022-12-04
* Author: IsChristina (christinaxia77@foxmail.com)
*/

const Tree = require("../include/TreeNode");
const { printTree } = require("../include/PrintUtil");

/* 二叉搜索树 */
var root;

function BinarySearchTree(nums) {
nums.sort((a,b) => { return a-b }); // 排序数组
root = buildTree(nums, 0, nums.length - 1); // 构建二叉搜索树
}

/* 获取二叉树根结点 */
function getRoot() {
return root;
}

/* 构建二叉搜索树 */
function buildTree(nums, i, j) {
if (i > j) return null;
// 将数组中间结点作为根结点
let mid = Math.floor((i + j) / 2);
let root = new Tree.TreeNode(nums[mid]);
// 递归建立左子树和右子树
root.left = buildTree(nums, i, mid - 1);
root.right = buildTree(nums, mid + 1, j);
return root;
}

/* 查找结点 */
function search(num) {
let cur = root;
// 循环查找,越过叶结点后跳出
while (cur !== null) {
// 目标结点在 root 的右子树中
if (cur.val < num) cur = cur.right;
// 目标结点在 root 的左子树中
else if (cur.val > num) cur = cur.left;
// 找到目标结点,跳出循环
else break;
}
// 返回目标结点
return cur;
}

/* 插入结点 */
function insert(num) {
// 若树为空,直接提前返回
if (root === null) return null;
let cur = root, pre = null;
// 循环查找,越过叶结点后跳出
while (cur !== null) {
// 找到重复结点,直接返回
if (cur.val === num) return null;
pre = cur;
// 插入位置在 root 的右子树中
if (cur.val < num) cur = cur.right;
// 插入位置在 root 的左子树中
else cur = cur.left;
}
// 插入结点 val
let node = new Tree.TreeNode(num);
if (pre.val < num) pre.right = node;
else pre.left = node;
return node;
}

/* 删除结点 */
function remove(num) {
// 若树为空,直接提前返回
if (root === null) return null;
let cur = root, pre = null;
// 循环查找,越过叶结点后跳出
while (cur !== null) {
// 找到待删除结点,跳出循环
if (cur.val === num) break;
pre = cur;
// 待删除结点在 root 的右子树中
if (cur.val < num) cur = cur.right;
// 待删除结点在 root 的左子树中
else cur = cur.left;
}
// 若无待删除结点,则直接返回
if (cur === null) return null;
// 子结点数量 = 0 or 1
if (cur.left === null || cur.right === null) {
// 当子结点数量 = 0 / 1 时, child = null / 该子结点
let child = cur.left !== null ? cur.left : cur.right;
// 删除结点 cur
if (pre.left === cur) pre.left = child;
else pre.right = child;
}
// 子结点数量 = 2
else {
// 获取中序遍历中 cur 的下一个结点
let nex = min(cur.right);
let tmp = nex.val;
// 递归删除结点 nex
remove(nex.val);
// 将 nex 的值复制给 cur
cur.val = tmp;
}
return cur;
}

/* 获取最小结点 */
function min(root) {
if (root === null) return root;
// 循环访问左子结点,直到叶结点时为最小结点,跳出
while (root.left !== null) {
root = root.left;
}
return root;
}

/* Driver Code */
/* 初始化二叉搜索树 */
var nums = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ];
BinarySearchTree(nums)
console.log("\n初始化的二叉树为\n");
printTree(getRoot());

/* 查找结点 */
let node = search(5);
console.log("\n查找到的结点对象为 " + node + ",结点值 = " + node.val);

/* 插入结点 */
node = insert(16);
console.log("\n插入结点 16 后,二叉树为\n");
printTree(getRoot());

/* 删除结点 */
remove(1);
console.log("\n删除结点 1 后,二叉树为\n");
printTree(getRoot());
remove(2);
console.log("\n删除结点 2 后,二叉树为\n");
printTree(getRoot());
remove(4);
console.log("\n删除结点 4 后,二叉树为\n");
printTree(getRoot());
35 changes: 35 additions & 0 deletions codes/javascript/chapter_tree/binary_tree.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* File: binary_tree.js
* Created Time: 2022-12-04
* Author: IsChristina (christinaxia77@foxmail.com)
*/

const Tree = require("../include/TreeNode");
const { printTree } = require("../include/PrintUtil");

/* 初始化二叉树 */
// 初始化结点
let n1 = new Tree.TreeNode(1),
n2 = new Tree.TreeNode(2),
n3 = new Tree.TreeNode(3),
n4 = new Tree.TreeNode(4),
n5 = new Tree.TreeNode(5);
// 构建引用指向(即指针)
n1.left = n2;
n1.right = n3;
n2.left = n4;
n2.right = n5;
console.log("\n初始化二叉树\n")
printTree(n1)

/* 插入与删除结点 */
let P = new Tree.TreeNode(0);
// 在 n1 -> n2 中间插入结点 P
n1.left = P;
P.left = n2;
console.log("\n插入结点 P 后\n");
printTree(n1);
// 删除结点 P
n1.left = n2;
console.log("\n删除结点 P 后\n");
printTree(n1);
37 changes: 37 additions & 0 deletions codes/javascript/chapter_tree/binary_tree_bfs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* File: binary_tree.js
* Created Time: 2022-12-04
* Author: IsChristina (christinaxia77@foxmail.com)
*/

const { arrToTree } = require("../include/TreeNode");
const { printTree } = require("../include/PrintUtil");

/* 层序遍历 */
function hierOrder(root) {
// 初始化队列,加入根结点
let queue = [root];
// 初始化一个列表,用于保存遍历序列
let list = [];
while (queue.length) {
let node = queue.shift(); // 队列出队
list.push(node.val); // 保存结点
if (node.left)
queue.push(node.left); // 左子结点入队
if (node.right)
queue.push(node.right); // 右子结点入队

}
return list;
}

/* Driver Code */
/* 初始化二叉树 */
// 这里借助了一个从数组直接生成二叉树的函数
var root = arrToTree([1, 2, 3, 4, 5, 6, 7, null, null, null, null, null, null, null, null ]);
console.log("\n初始化二叉树\n");
printTree(root);

/* 层序遍历 */
let list = hierOrder(root);
console.log("\n层序遍历的结点打印序列 = " + list);
61 changes: 61 additions & 0 deletions codes/javascript/chapter_tree/binary_tree_dfs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* File: binary_tree.js
* Created Time: 2022-12-04
* Author: IsChristina (christinaxia77@foxmail.com)
*/

const { arrToTree } = require("../include/TreeNode");
const { printTree } = require("../include/PrintUtil");

// 初始化列表,用于存储遍历序列
var list = []

/* 前序遍历 */
function preOrder(root){
if (root === null) return;
// 访问优先级:根结点 -> 左子树 -> 右子树
list.push(root.val);
preOrder(root.left);
preOrder(root.right);
}

/* 中序遍历 */
function inOrder(root) {
if (root === null) return;
// 访问优先级:左子树 -> 根结点 -> 右子树
inOrder(root.left);
list.push(root.val);
inOrder(root.right);
}

/* 后序遍历 */
function postOrder(root) {
if (root === null) return;
// 访问优先级:左子树 -> 右子树 -> 根结点
postOrder(root.left);
postOrder(root.right);
list.push(root.val);
}

/* Driver Code */
/* 初始化二叉树 */
// 这里借助了一个从数组直接生成二叉树的函数
var root = arrToTree([1, 2, 3, 4, 5, 6, 7, null, null, null, null, null, null, null, null]);
console.log("\n初始化二叉树\n");
printTree(root);

/* 前序遍历 */
list.length = 0;
preOrder(root);
console.log("\n前序遍历的结点打印序列 = " + list);

/* 中序遍历 */
list.length = 0;
inOrder(root);
console.log("\n中序遍历的结点打印序列 = " + list);

/* 后序遍历 */
list.length = 0;
postOrder(root);
console.log("\n后序遍历的结点打印序列 = " + list);

88 changes: 88 additions & 0 deletions codes/javascript/include/PrintUtil.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/**
* File: PrintUtil.js
* Created Time: 2022-12-04
* Author: IsChristina (christinaxia77@foxmail.com)
*/

function Trunk(prev, str) {
this.prev = prev;
this.str = str;
}

/**
* Print a linked list
* @param head
*/
function printLinkedList(head) {
let list = [];
while (head !== null) {
list.push(head.val.toString());
head = head.next;
}
console.log(list.join(" -> "));
}

/**
* The interface of the tree printer
* This tree printer is borrowed from TECHIE DELIGHT
* https://www.techiedelight.com/c-program-print-binary-tree/
* @param root
*/
function printTree(root) {
printTree(root, null, false);
}

/**
* Print a binary tree
* @param root
* @param prev
* @param isLeft
*/
function printTree(root, prev, isLeft) {
if (root === null) {
return;
}

let prev_str = " ";
let trunk = new Trunk(prev, prev_str);

printTree(root.right, trunk, true);

if (!prev) {
trunk.str = "———";
} else if (isLeft) {
trunk.str = "/———";
prev_str = " |";
} else {
trunk.str = "\\———";
prev.str = prev_str;
}

showTrunks(trunk);
console.log(" " + root.val);

if (prev) {
prev.str = prev_str;
}
trunk.str = " |";

printTree(root.left, trunk, false);
}

/**
* Helper function to print branches of the binary tree
* @param p
*/
function showTrunks(p) {
if (!p) {
return;
}

showTrunks(p.prev);
console.log(p.str);
}

module.exports = {
printTree,
printLinkedList,
}
Loading