用 js 實現的二叉樹數據結構,完成 先/中/后 序遍歷、查找最 大/小 值、查找特定值以及刪除節點(雖然沒太理解)的操作。
// 節點對象
class Node {
constructor(data) {
this.root = this;
this.data = data;
this.left = null;
this.right = null;
}
}
// 二叉樹
class BST {
constructor() {
this.root = null;
}
// 插入節點
insert(data) {
let newNode = new Node(data);
let insertNode = (node, newNode) => {
if (newNode.data < node.data) {
if (node.left === null) {
node.left = newNode;
} else {
insertNode(node.left, newNode);
}
} else {
if (node.right === null) {
node.right = newNode;
} else {
insertNode(node.right, newNode)
}
}
};
if (!this.root) {
this.root = newNode;
} else {
insertNode(this.root, newNode)
}
}
/* 中序遍歷 =>
1.訪問左子樹(先訪問左子樹中的左子樹,再訪問左子樹中的右子樹);
2.訪問根
3.訪問右子樹(先訪問右子樹中的左子樹,再訪問右子樹中的右子樹)
可以起到排序作用
*/
inOrder() {
let backs = [];
let inOrderNode = (node, callback) => {
if (node !== null) {
inOrderNode(node.left, callback);
backs.push(callback(node.data));
inOrderNode(node.right, callback);
}
}
let callback = function(v) {
return v
}
inOrderNode(this.root, callback);
return backs
}
// 前序遍歷 => 1.訪問根節點; 2.訪問左子樹; 3.訪問右子樹
preOrder() {
let backs = [];
let preOrderNode = (node, callback) => {
if (node !== null) {
backs.push(callback(node.data));
preOrderNode(node.left, callback);
preOrderNode(node.right, callback);
}
}
let callback = function(v) {
return v
}
preOrderNode(this.root, callback);
return backs
}
/* 后序遍歷 =>
1.訪問左子樹。(先訪問左子樹中的左子樹,再訪問左子樹中的右子樹)
2.訪問右子樹。(先訪問右子樹中的左子樹,再訪問右子樹中的右子樹)
3.訪問根
*/
postOrder(){
let backs = [];
const postOrderNode = (node,callback) => {
if(node !== null){
postOrderNode(node.left,callback);
postOrderNode(node.right,callback);
backs.push(callback(node.data))
}
};
let callback = function(v) {
return v
}
postOrderNode(this.root,callback);
return backs
}
// 查找最小值
getMin(node) {
let minNode = node => {
return node ? (node.left ? minNode(node.left) : node) : null
}
return minNode(node || this.root)
}
// 查找最大值
getMax(node) {
let maxNode = node => {
return node ? (node.right ? maxNode(node.right) : node) : null
}
return maxNode(node || this.root)
}
// 查找特定值
find(data) {
let findNode = (node, data) => {
if (node == null) return false
if (node.data === data) return node;
return findNode((data < node.data) ? node.left : node.right, data);
}
return findNode(this.root, data);
}
// 刪除節點
// 返回新的二叉樹?
remove(data) {
let removeNode = (node, data) => {
if (node === null) return null;
if (node.data === data) {
if (node.left === null && node.right === null) return null
if (node.left === null) return node.right;
if (node.right === null) return node.left;
if (node.left !== null && node.right !== null) {
let _node = this.getMin(node.right);
node.data = _node.data;
node.right = removeNode(node.right, data);
return node
}
} else if (data < node.data) {
node.left = removeNode(node.left, data);
return node;
} else {
node.right = removeNode(node.right, data);
return node;
}
}
return removeNode(this.root, data)
}
}
/***********************************/
// some operation
let datas = [11,7,5,3,6,9,8,10,20,14,12,25,18];
let bst = new BST();
datas.forEach(data => {
bst.insert(data)
})
console.log(bst.getMax())
console.log(bst.getMin())
另一個實例:
class BNode {
constructor(val) {
this.value = val;
this.left = null;
this.right = null;
}
}
class BinaryTree {
constructor() {
this.root = null;
this.values = new Array();
}
/**
* insert 插入節點
* @param {[ type ]} val [description]
* @return {[ void ]} [description]
*/
insert(val) {
this.values.push(val);
let node = new BNode(val);
if (!this.root) {
this.root = node;
} else {
this._insertNode(this.root, node);
}
}
/**
* _insertNode 遞歸插入節點
* @param {[ BinaryNode ]} node [父節點]
* @param {[ BinaryNode ]} newNode [新子節點]
*/
_insertNode(node, newNode) {
if (newNode.value < node.value) {
if (node.left === null ){
node.left = newNode;
} else {
this._insertNode(node.left, newNode);
}
} else {
if (node.right === null) {
node.right = newNode;
} else {
this._insertNode(node.right, newNode);
}
}
}
/**
* [inOrderTraverse 中序遍歷]
* @return {[ Array ]} [description]
*/
inOrderTraverse() {
let result = new Array();
this._inOrderTraverseNode(this.root, node => {
result.push(node.value);
})
return result;
}
/**
* [_inOrderTraverseNode 中序遍歷遞歸]
* @param {[ BinaryNode ]} node [當前節點]
* @param { Function } callback [回調函數]
* @return {[ void ]} [description]
*/
_inOrderTraverseNode(node, callback) {
if (node) {
this._inOrderTraverseNode(node.left, callback);
callback(node);
this._inOrderTraverseNode(node.right, callback);
}
}
/**
* [preOrderTraverse 先序遍歷]
* @return {[ Array ]} [description]
*/
preOrderTraverse() {
let result = new Array();
this._preOrderTraverseNode(this.root, node => {
result.push(node.value);
})
return result;
}
/**
* [_preOrderTraverseNode 先序遍歷遞歸]
* @param {[ BinaryNode ]} node [當前節點]
* @param { Function } callback [回調函數]
* @return {[ Void ]} [description]
*/
_preOrderTraverseNode(node, callback) {
if (node) {
callback(node);
this._preOrderTraverseNode(node.left, callback);
this._preOrderTraverseNode(node.right, callback);
}
}
/**
* [postOrderTraverse 后序遍歷]
* @return {[Array]} [description]
*/
postOrderTraverse() {
let result = new Array();
this._postOrderTraverseNode(this.root, node => {
result.push(node.value);
})
return result;
}
/**
* [_postOrderTraverseNode 后序遍歷遞歸]
* @param {[BinaryNode]} node [當前節點]
* @param {Function} callback [回調函數]
* @return {[type]} [description]
*/
_postOrderTraverseNode(node, callback) {
if (node) {
this._postOrderTraverseNode(node.left, callback);
this._postOrderTraverseNode(node.right, callback);
callback(node);
}
}
/**
* [remove 移除指定值]
* @param {[*]} val [目標值]
* @return {[ Void ]} [description]
*/
remove(val) {
this.root = this._removeNode(this.root, val);
}
/**
* [_removeNode 移除節點遞歸]
* @param {[BinaryNode]} node [當前節點]
* @param {[*]} val [要移的除節點值]
* @return {[BinaryNode]} [當前節點]
*/
_removeNode(node, val) {
if (node === null) return null;
// 遞歸尋找目標節點
if (val < node.value) {
this._removeNode(node.left, val);
return node;
}
if (val > node.value) {
this._removeNode(node.right, val);
return node;
}
// 找到目標節點
if (val === node.value) {
// 是葉子節點 (left\right沒有節點)
if (node.left === null && node.right === null) {
// 賦值 null, 表示刪除
node = null;
return node;
}
// 只有一個子節點
if (node.left === null) {
node = node.right;
return node;
}
if (node.right === null) {
node = node.left;
return node;
}
// 左右子節點都有
let min_node = this._findMinNode(node);
node.value = min_node.value;
node.right = this._removeNode(node.right, min_node.value);
return node;
}
}
/**
* [_findMinNode 查找最小節點]
* @param {[BinaryNode]} node [當前節點]
* @return {[BinaryNode]} [最小的節點]
*/
_findMinNode(node) {
while(node && node.left) {
node = node.left;
}
return node;
}
/**
* [search 檢索]
* @param {[ * ]} val [被檢索值]
* @return {[ Boolean ]} [表示是否存在]
*/
search(val) {
let values = this.inOrderTraverse();
return values.includes(val);
}
/**
* [min 返回最小值]
* @return {[ type ]} 最小值
*/
min() {
let values = this.inOrderTraverse();
return values[0]
}
/**
* [max 返回最小值]
* @return {[ type ]} 最大值
*/
max() {
let values = this.inOrderTraverse();
return values[values.length - 1]
}
/**
* [isEmpty 是否為空二叉樹]
* @return {Boolean}
*/
isEmpty() {
return this.root === null;
}
/**
* [breadthFirstSearch 廣度優先遍歷]
* @return {[Array]} [遍歷后結果]
*/
breadthFirstSearch() {
let result = new Array();
let content = new Array();
let current_node = null;
content.push(this.root);
while(content.length) {
current_node = content.shift();
result.push(current_node.value);
if (current_node.right) {
content.push(current_node.right);
}
if (current_node.left) {
content.push(current_node.left);
}
}
return result;
}
}
