【從蛋殼到滿天飛】JS 數據結構解析和算法實現,所有文章大概的內容以下: Arrays(數組)、Stacks(棧)、Queues(隊列)、LinkedList(鏈表)、Recursion(遞歸思想)、BinarySearchTree(二分搜索樹)、Set(集合)、Map(映射)、Heap(堆)、PriorityQueue(優先隊列)、SegmentTree(線段樹)、Trie(字典樹)、UnionFind(並查集)、AVLTree(AVL 平衡樹)、RedBlackTree(紅黑平衡樹)、HashTable(哈希表)javascript
源代碼有三個:ES6(單個單個的 class 類型的 js 文件) | JS + HTML(一個 js 配合一個 html)| JAVA (一個一個的工程)php
所有源代碼已上傳 github,點擊我吧,光看文章可以掌握兩成,動手敲代碼、動腦思考、畫圖才能夠掌握八成。html
本文章適合 對數據結構想了解而且感興趣的人羣,文章風格一如既往如此,就以爲手機上看起來比較方便,這樣顯得比較有條理,整理這些筆記加源碼,時間跨度也算將近半年時間了,但願對想學習數據結構的人或者正在學習數據結構的人羣有幫助。前端
堆
以及並查集
,class Node {
e; // Element
left; // Node
right; // Node
}
複製代碼
二分搜索樹其實不是支持全部的類型java
代碼實現node
class MyBinarySearchTreeNode {
constructor(element, left, right) {
// 實際存儲的元素
this.element = element;
// 當前節點的左子樹
this.left = left;
// 當前節點的右子樹
this.right = right;
}
}
class MyBinarySearchTree {
constructor() {
this.root = null;
this.size = 0;
}
// 獲取二分搜索樹中節點個數
getSize() {
return this.size;
}
// 返回二分搜索樹是否爲空的bool值
isEmpty() {
return this.size === 0;
}
}
複製代碼
代碼python
class MyBinarySearchTreeNode {
constructor(element, left = null, right = null) {
// 實際存儲的元素
this.element = element;
// 當前節點的左子樹
this.left = left;
// 當前節點的右子樹
this.right = right;
}
}
class MyBinarySearchTree {
constructor() {
this.root = null;
this.size = 0;
}
// 添加元素到二分搜索樹中 +
add(element) {
if (element === null) throw new Error("element is null. can't store.");
if (this.root === null) {
this.root = new MyBinarySearchTreeNode(element);
this.size++;
} else this.root = this.recursiveAdd(this.root, element);
}
// 添加元素到二分搜索樹中 遞歸算法 -
recursiveAdd(node, newElement) {
// 解決最基本的問題 也就是遞歸函數調用的終止條件
if (node === null) {
node = new MyBinarySearchTreeNode(newElement);
this.size++;
return node;
}
// 1. 當前節點的元素比新元素大
// 那麼新元素就會被添加到當前節點的左子樹去
// 2. 當前節點的元素比新元素小
// 那麼新元素就會被添加到當前節點的右子樹去
// 3. 當前節點的元素比新元素相等
// 什麼都不作了,由於目前不添加劇復的元素
if (this.compare(node.element, newElement) > 0)
node.left = this.recursiveAdd(node.left, newElement);
else if (this.compare(node.element, newElement) < 0)
node.right = this.recursiveAdd(node.right, newElement);
else {
}
// 將複雜問題分解成多個性質相同的小問題,
// 而後求出小問題的答案,
// 最終構建出原問題的答案
return node;
}
// 獲取二分搜索樹中節點個數 +
getSize() {
return this.size;
}
// 返回二分搜索樹是否爲空的bool值 +
isEmpty() {
return this.size === 0;
}
// 新增一個比較的方法,專門用來比較新增的元素大小 -
// 第一個元素比第二個元素大 就返回 1
// 第一個元素比第二個元素小 就返回 -1
// 第一個元素比第二個元素相等 就返回 0
compare(elementA, elementB) {
if (elementA === null || elementB === null)
throw new Error("element is null. can't compare.");
// 先直接寫死
if (elementA > elementB) return 1;
else if (elementA < elementB) return -1;
else return 0;
}
}
複製代碼
對於二分搜索的插入操做c++
代碼git
class MyBinarySearchTreeNode {
constructor(element, left = null, right = null) {
// 實際存儲的元素
this.element = element;
// 當前節點的左子樹
this.left = left;
// 當前節點的右子樹
this.right = right;
}
}
class MyBinarySearchTree {
constructor() {
this.root = null;
this.size = 0;
}
// 添加元素到二分搜索樹中 +
add(element) {
if (element === null) throw new Error("element is null. can't store.");
this.root = this.recursiveAdd(this.root, element);
}
// 添加元素到二分搜索樹中 遞歸算法 -
recursiveAdd(node, newElement) {
// 解決最基本的問題 也就是遞歸函數調用的終止條件
if (node === null) {
this.size++;
return new MyBinarySearchTreeNode(newElement);
}
// 1. 當前節點的元素比新元素大
// 那麼新元素就會被添加到當前節點的左子樹去
// 2. 當前節點的元素比新元素小
// 那麼新元素就會被添加到當前節點的右子樹去
// 3. 當前節點的元素比新元素相等
// 什麼都不作了,由於目前不添加劇復的元素
if (this.compare(node.element, newElement) > 0)
node.left = this.recursiveAdd(node.left, newElement);
else if (this.compare(node.element, newElement) < 0)
node.right = this.recursiveAdd(node.right, newElement);
else {
}
// 將複雜問題分解成多個性質相同的小問題,
// 而後求出小問題的答案,
// 最終構建出原問題的答案
return node;
}
// 獲取二分搜索樹中節點個數 +
getSize() {
return this.size;
}
// 返回二分搜索樹是否爲空的bool值 +
isEmpty() {
return this.size === 0;
}
// 新增一個比較的方法,專門用來比較新增的元素大小 -
// 第一個元素比第二個元素大 就返回 1
// 第一個元素比第二個元素小 就返回 -1
// 第一個元素比第二個元素相等 就返回 0
compare(elementA, elementB) {
if (elementA === null || elementB === null)
throw new Error("element is null. can't compare.");
// 先直接寫死
if (elementA > elementB) return 1;
else if (elementA < elementB) return -1;
else return 0;
}
}
複製代碼
雖然代碼量更少了,可是也更難理解的了一些github
代碼
class MyBinarySearchTreeNode {
constructor(element, left = null, right = null) {
// 實際存儲的元素
this.element = element;
// 當前節點的左子樹
this.left = left;
// 當前節點的右子樹
this.right = right;
}
}
class MyBinarySearchTree {
constructor() {
this.root = null;
this.size = 0;
}
// 添加元素到二分搜索樹中 +
add(element) {
if (element === null) throw new Error("element is null. can't store.");
this.root = this.recursiveAdd(this.root, element);
}
// 添加元素到二分搜索樹中 遞歸算法 -
recursiveAdd(node, newElement) {
// 解決最基本的問題 也就是遞歸函數調用的終止條件
if (node === null) {
this.size++;
return new MyBinarySearchTreeNode(newElement);
}
// 1. 當前節點的元素比新元素大
// 那麼新元素就會被添加到當前節點的左子樹去
// 2. 當前節點的元素比新元素小
// 那麼新元素就會被添加到當前節點的右子樹去
// 3. 當前節點的元素比新元素相等
// 什麼都不作了,由於目前不添加劇復的元素
if (this.compare(node.element, newElement) > 0)
node.left = this.recursiveAdd(node.left, newElement);
else if (this.compare(node.element, newElement) < 0)
node.right = this.recursiveAdd(node.right, newElement);
else {
}
// 將複雜問題分解成多個性質相同的小問題,
// 而後求出小問題的答案,
// 最終構建出原問題的答案
return node;
}
// 判斷二分搜索樹中是否包含某個元素 +
contains(element) {
if (this.root === null) throw new Error("root is null. can't query.");
return this.recursiveContains(this.root, element);
}
// 判斷二分搜索樹種是否包含某個元素 遞歸算法 -
recursiveContains(node, element) {
if (node === null) return false;
// 當前節點元素比 要搜索的元素 大
if (this.compare(node.element, element) > 0)
return this.recursiveContains(node.left, element);
else if (this.compare(node.element, element) < 0)
// 當前元素比 要搜索的元素 小
return this.recursiveContains(node.right, element);
// 兩個元素相等
else return true;
}
// 獲取二分搜索樹中節點個數 +
getSize() {
return this.size;
}
// 返回二分搜索樹是否爲空的bool值 +
isEmpty() {
return this.size === 0;
}
// 新增一個比較的方法,專門用來比較新增的元素大小 -
// 第一個元素比第二個元素大 就返回 1
// 第一個元素比第二個元素小 就返回 -1
// 第一個元素比第二個元素相等 就返回 0
compare(elementA, elementB) {
if (elementA === null || elementB === null)
throw new Error("element is null. can't compare.");
// 先直接寫死
if (elementA > elementB) return 1;
else if (elementA < elementB) return -1;
else return 0;
}
}
複製代碼
遍歷操做就是把這個數據結構中全部的元素都訪問一遍
訪問數據結構中存儲的全部元素是由於與業務相關,
在線性結構下,遍歷是極其容易的
在樹結構下遍歷操做並無那麼難
對於遍歷操做,兩個子樹都要顧及
// 遍歷以node爲根的二分搜索樹 遞歸算法
function traverse(node) {
if (node === null) {
return;
}
// ... 要作的事情
// 訪問該節點 兩邊都要顧及
// 訪問該節點的時候就去作該作的事情,
// 如 給全部學生加兩分
traverse(node.left);
traverse(node.right);
}
// 寫法二 這種邏輯也是能夠的
function traverse(node) {
if (node !== null) {
// ... 要作的事情
// 訪問該節點 兩邊都要顧及
// 訪問該節點的時候就去作該作的事情,
// 如 給全部學生加兩分
traverse(node.left);
traverse(node.right);
}
}
複製代碼
(class: MyBinarySearchTree, class: Main)
MyBinarySearchTree
class MyBinarySearchTreeNode {
constructor(element, left = null, right = null) {
// 實際存儲的元素
this.element = element;
// 當前節點的左子樹
this.left = left;
// 當前節點的右子樹
this.right = right;
}
}
class MyBinarySearchTree {
constructor() {
this.root = null;
this.size = 0;
}
// 添加元素到二分搜索樹中 +
add(element) {
if (element === null) throw new Error("element is null. can't store.");
this.root = this.recursiveAdd(this.root, element);
}
// 添加元素到二分搜索樹中 遞歸算法 -
recursiveAdd(node, newElement) {
// 解決最基本的問題 也就是遞歸函數調用的終止條件
if (node === null) {
this.size++;
return new MyBinarySearchTreeNode(newElement);
}
// 1. 當前節點的元素比新元素大
// 那麼新元素就會被添加到當前節點的左子樹去
// 2. 當前節點的元素比新元素小
// 那麼新元素就會被添加到當前節點的右子樹去
// 3. 當前節點的元素比新元素相等
// 什麼都不作了,由於目前不添加劇復的元素
if (this.compare(node.element, newElement) > 0)
node.left = this.recursiveAdd(node.left, newElement);
else if (this.compare(node.element, newElement) < 0)
node.right = this.recursiveAdd(node.right, newElement);
else {
}
// 將複雜問題分解成多個性質相同的小問題,
// 而後求出小問題的答案,
// 最終構建出原問題的答案
return node;
}
// 判斷二分搜索樹中是否包含某個元素 +
contains(element) {
if (this.root === null) throw new Error("root is null. can't query.");
return this.recursiveContains(this.root, element);
}
// 判斷二分搜索樹種是否包含某個元素 遞歸算法 -
recursiveContains(node, element) {
if (node === null) return false;
// 當前節點元素比 要搜索的元素 大
if (this.compare(node.element, element) > 0)
return this.recursiveContains(node.left, element);
else if (this.compare(node.element, element) < 0)
// 當前元素比 要搜索的元素 小
return this.recursiveContains(node.right, element);
// 兩個元素相等
else return true;
}
// 前序遍歷 +
preOrder(operator) {
this.recursivePreOrder(this.root, operator);
}
// 前序遍歷 遞歸算法 -
recursivePreOrder(node, operator) {
if (node === null) return;
// 調用一下操做方法
operator(node.element);
console.log(node, node.element);
// 繼續遞歸遍歷左右子樹
this.recursivePreOrder(node.left, operator);
this.recursivePreOrder(node.right, operator);
}
// 獲取二分搜索樹中節點個數 +
getSize() {
return this.size;
}
// 返回二分搜索樹是否爲空的bool值 +
isEmpty() {
return this.size === 0;
}
// 新增一個比較的方法,專門用來比較新增的元素大小 -
// 第一個元素比第二個元素大 就返回 1
// 第一個元素比第二個元素小 就返回 -1
// 第一個元素比第二個元素相等 就返回 0
compare(elementA, elementB) {
if (elementA === null || elementB === null)
throw new Error("element is null. can't compare.");
// 先直接寫死
if (elementA > elementB) return 1;
else if (elementA < elementB) return -1;
else return 0;
}
}
複製代碼
Main
class Main {
constructor() {
this.alterLine('MyBinarySearchTree Area');
let myBinarySearchTree = new MyBinarySearchTree();
let nums = [5, 3, 6, 8, 4, 2];
for (var i = 0; i < nums.length; i++) {
myBinarySearchTree.add(nums[i]);
}
/////////////////
// 5 //
// / \ //
// 3 6 //
// / \ \ //
// 2 4 8 //
/////////////////
myBinarySearchTree.preOrder(this.show);
this.show(myBinarySearchTree.contains(1));
console.log(myBinarySearchTree.contains(1));
}
// 將內容顯示在頁面上
show(content) {
document.body.innerHTML += `${content}<br /><br />`;
}
// 展現分割線
alterLine(title) {
let line = `--------------------${title}----------------------`;
console.log(line);
document.body.innerHTML += `${line}<br /><br />`;
}
}
window.onload = function() {
// 執行主函數
new Main();
};
複製代碼
(class: MyBinarySearchTree, class: Main)
MyBinarySearchTree
class MyBinarySearchTreeNode {
constructor(element, left = null, right = null) {
// 實際存儲的元素
this.element = element;
// 當前節點的左子樹
this.left = left;
// 當前節點的右子樹
this.right = right;
}
}
class MyBinarySearchTree {
constructor() {
this.root = null;
this.size = 0;
}
// 添加元素到二分搜索樹中 +
add(element) {
if (element === null) throw new Error("element is null. can't store.");
this.root = this.recursiveAdd(this.root, element);
}
// 添加元素到二分搜索樹中 遞歸算法 -
recursiveAdd(node, newElement) {
// 解決最基本的問題 也就是遞歸函數調用的終止條件
if (node === null) {
this.size++;
return new MyBinarySearchTreeNode(newElement);
}
// 1. 當前節點的元素比新元素大
// 那麼新元素就會被添加到當前節點的左子樹去
// 2. 當前節點的元素比新元素小
// 那麼新元素就會被添加到當前節點的右子樹去
// 3. 當前節點的元素比新元素相等
// 什麼都不作了,由於目前不添加劇復的元素
if (this.compare(node.element, newElement) > 0)
node.left = this.recursiveAdd(node.left, newElement);
else if (this.compare(node.element, newElement) < 0)
node.right = this.recursiveAdd(node.right, newElement);
else {
}
// 將複雜問題分解成多個性質相同的小問題,
// 而後求出小問題的答案,
// 最終構建出原問題的答案
return node;
}
// 判斷二分搜索樹中是否包含某個元素 +
contains(element) {
if (this.root === null) throw new Error("root is null. can't query.");
return this.recursiveContains(this.root, element);
}
// 判斷二分搜索樹種是否包含某個元素 遞歸算法 -
recursiveContains(node, element) {
if (node === null) return false;
// 當前節點元素比 要搜索的元素 大
if (this.compare(node.element, element) > 0)
return this.recursiveContains(node.left, element);
else if (this.compare(node.element, element) < 0)
// 當前元素比 要搜索的元素 小
return this.recursiveContains(node.right, element);
// 兩個元素相等
else return true;
}
// 前序遍歷 +
preOrder(operator) {
this.recursivePreOrder(this.root, operator);
}
// 前序遍歷 遞歸算法 -
recursivePreOrder(node, operator) {
if (node === null) return;
// 調用一下操做方法
operator(node.element);
console.log(node, node.element);
// 繼續遞歸遍歷左右子樹
this.recursivePreOrder(node.left, operator);
this.recursivePreOrder(node.right, operator);
}
// 獲取二分搜索樹中節點個數 +
getSize() {
return this.size;
}
// 返回二分搜索樹是否爲空的bool值 +
isEmpty() {
return this.size === 0;
}
// 新增一個比較的方法,專門用來比較新增的元素大小 -
// 第一個元素比第二個元素大 就返回 1
// 第一個元素比第二個元素小 就返回 -1
// 第一個元素比第二個元素相等 就返回 0
compare(elementA, elementB) {
if (elementA === null || elementB === null)
throw new Error("element is null. can't compare.");
// 先直接寫死
if (elementA > elementB) return 1;
else if (elementA < elementB) return -1;
else return 0;
}
// 輸出二分搜索樹中的信息
// @Override toString 2018-11-03-jwl
toString() {
let treeInfo = '';
treeInfo += this.getBinarySearchTreeString(this.root, 0, treeInfo);
return treeInfo;
}
// 寫一個輔助函數,用來生成二分搜索樹信息的字符串
getBinarySearchTreeString(node, depth, treeInfo, pageContent = '') {
//之前序遍歷的方式
if (node === null) {
treeInfo += this.getDepthString(depth) + 'null \r\n';
pageContent = this.getDepthString(depth) + 'null<br /><br />';
document.body.innerHTML += `${pageContent}`;
return treeInfo;
}
treeInfo += this.getDepthString(depth) + node.element + '\r\n';
pageContent =
this.getDepthString(depth) + node.element + '<br /><br />';
document.body.innerHTML += `${pageContent}`;
treeInfo = this.getBinarySearchTreeString(
node.left,
depth + 1,
treeInfo
);
treeInfo = this.getBinarySearchTreeString(
node.right,
depth + 1,
treeInfo
);
return treeInfo;
}
// 寫一個輔助函數,用來生成遞歸深度字符串
getDepthString(depth) {
let depthString = '';
for (var i = 0; i < depth; i++) {
depthString += '-- ';
}
return depthString;
}
}
複製代碼
Main
class Main {
constructor() {
this.alterLine('MyBinarySearchTree Area');
let myBinarySearchTree = new MyBinarySearchTree();
let nums = [5, 3, 6, 8, 4, 2];
for (var i = 0; i < nums.length; i++) {
myBinarySearchTree.add(nums[i]);
}
/////////////////
// 5 //
// / \ //
// 3 6 //
// / \ \ //
// 2 4 8 //
/////////////////
console.log(myBinarySearchTree.toString());
}
// 將內容顯示在頁面上
show(content) {
document.body.innerHTML += `${content}<br /><br />`;
}
// 展現分割線
alterLine(title) {
let line = `--------------------${title}----------------------`;
console.log(line);
document.body.innerHTML += `${line}<br /><br />`;
}
}
window.onload = function() {
// 執行主函數
new Main();
};
複製代碼
前序遍歷
前
表示先訪問的這個節點。function preOrder(node) {
if (node == null) return;
// ... 要作的事情
// 訪問該節點
// 先一直往左,而後不斷返回上一層 再向左、終止,
// 最後整個操做循環往復,直到所有終止。
preOrder(node.left);
preOrder(node.right);
}
複製代碼
中序遍歷
中
表示先訪問左子樹,function inOrder(node) {
if (node == null) return;
inOrder(node.left);
// ... 要作的事情
// 訪問該節點
inOrder(node.right);
}
複製代碼
中序遍歷後輸出的結果是排序後的結果。
後序遍歷
後
表示先訪問左子樹,function inOrder(node) {
if (node == null) return;
inOrder(node.left);
inOrder(node.right);
// ... 要作的事情
// 訪問該節點
}
複製代碼
二分搜索樹的前序遍歷和後序遍歷並不像中序遍歷那樣進行了排序
java
、c#
、JS
這樣的語言都有垃圾回收機制,c++
語言中須要手動的控制內存,二分搜索樹的前中後序遍歷
(class: MyBinarySearchTree, class: Main)
MyBinarySearchTree
class MyBinarySearchTreeNode {
constructor(element, left = null, right = null) {
// 實際存儲的元素
this.element = element;
// 當前節點的左子樹
this.left = left;
// 當前節點的右子樹
this.right = right;
}
}
// 自定義二分搜索樹
class MyBinarySearchTree {
constructor() {
this.root = null;
this.size = 0;
}
// 添加元素到二分搜索樹中 +
add(element) {
if (element === null) throw new Error("element is null. can't store.");
this.root = this.recursiveAdd(this.root, element);
}
// 添加元素到二分搜索樹中 遞歸算法 -
recursiveAdd(node, newElement) {
// 解決最基本的問題 也就是遞歸函數調用的終止條件
if (node === null) {
this.size++;
return new MyBinarySearchTreeNode(newElement);
}
// 1. 當前節點的元素比新元素大
// 那麼新元素就會被添加到當前節點的左子樹去
// 2. 當前節點的元素比新元素小
// 那麼新元素就會被添加到當前節點的右子樹去
// 3. 當前節點的元素比新元素相等
// 什麼都不作了,由於目前不添加劇復的元素
if (this.compare(node.element, newElement) > 0)
node.left = this.recursiveAdd(node.left, newElement);
else if (this.compare(node.element, newElement) < 0)
node.right = this.recursiveAdd(node.right, newElement);
else {
}
// 將複雜問題分解成多個性質相同的小問題,
// 而後求出小問題的答案,
// 最終構建出原問題的答案
return node;
}
// 判斷二分搜索樹中是否包含某個元素 +
contains(element) {
if (this.root === null) throw new Error("root is null. can't query.");
return this.recursiveContains(this.root, element);
}
// 判斷二分搜索樹種是否包含某個元素 遞歸算法 -
recursiveContains(node, element) {
if (node === null) return false;
// 當前節點元素比 要搜索的元素 大
if (this.compare(node.element, element) > 0)
return this.recursiveContains(node.left, element);
else if (this.compare(node.element, element) < 0)
// 當前元素比 要搜索的元素 小
return this.recursiveContains(node.right, element);
// 兩個元素相等
else return true;
}
// 前序遍歷 +
preOrder(operator) {
this.recursivePreOrder(this.root, operator);
}
// 前序遍歷 遞歸算法 -
recursivePreOrder(node, operator) {
if (node === null) return;
// 調用一下操做方法
operator(node.element);
console.log(node, node.element);
// 繼續遞歸遍歷左右子樹
this.recursivePreOrder(node.left, operator);
this.recursivePreOrder(node.right, operator);
}
// 中序遍歷 +
inOrder(operator) {
this.recursiveInOrder(this.root, operator);
}
// 中序遍歷 遞歸算法 -
recursiveInOrder(node, operator) {
if (node == null) return;
this.recursiveInOrder(node.left, operator);
operator(node.element);
console.log(node.element);
this.recursiveInOrder(node.right, operator);
}
// 後序遍歷 +
postOrder(operator) {
this.recursivePostOrder(this.root, operator);
}
// 後序遍歷 遞歸算法 -
recursivePostOrder(node, operator) {
if (node == null) return;
this.recursivePostOrder(node.left, operator);
this.recursivePostOrder(node.right, operator);
operator(node.element);
console.log(node.element);
}
// 獲取二分搜索樹中節點個數 +
getSize() {
return this.size;
}
// 返回二分搜索樹是否爲空的bool值 +
isEmpty() {
return this.size === 0;
}
// 新增一個比較的方法,專門用來比較新增的元素大小 -
// 第一個元素比第二個元素大 就返回 1
// 第一個元素比第二個元素小 就返回 -1
// 第一個元素比第二個元素相等 就返回 0
compare(elementA, elementB) {
if (elementA === null || elementB === null)
throw new Error("element is null. can't compare.");
// 先直接寫死
if (elementA > elementB) return 1;
else if (elementA < elementB) return -1;
else return 0;
}
// 輸出二分搜索樹中的信息
// @Override toString 2018-11-03-jwl
toString() {
let treeInfo = '';
treeInfo += this.getBinarySearchTreeString(this.root, 0, treeInfo);
return treeInfo;
}
// 寫一個輔助函數,用來生成二分搜索樹信息的字符串
getBinarySearchTreeString(node, depth, treeInfo, pageContent = '') {
//之前序遍歷的方式
if (node === null) {
treeInfo += this.getDepthString(depth) + 'null \r\n';
pageContent = this.getDepthString(depth) + 'null<br /><br />';
document.body.innerHTML += `${pageContent}`;
return treeInfo;
}
treeInfo += this.getDepthString(depth) + node.element + '\r\n';
pageContent =
this.getDepthString(depth) + node.element + '<br /><br />';
document.body.innerHTML += `${pageContent}`;
treeInfo = this.getBinarySearchTreeString(
node.left,
depth + 1,
treeInfo
);
treeInfo = this.getBinarySearchTreeString(
node.right,
depth + 1,
treeInfo
);
return treeInfo;
}
// 寫一個輔助函數,用來生成遞歸深度字符串
getDepthString(depth) {
let depthString = '';
for (var i = 0; i < depth; i++) {
depthString += '-- ';
}
return depthString;
}
}
複製代碼
Main
// main 函數
class Main {
constructor() {
this.alterLine('MyBinarySearchTree Area');
let myBinarySearchTree = new MyBinarySearchTree();
let nums = [5, 3, 6, 8, 4, 2];
for (var i = 0; i < nums.length; i++) {
myBinarySearchTree.add(nums[i]);
}
/////////////////
// 5 //
// / \ //
// 3 6 //
// / \ \ //
// 2 4 8 //
/////////////////
this.alterLine('MyBinarySearchTree PreOrder Area');
myBinarySearchTree.preOrder(this.show);
this.alterLine('MyBinarySearchTree InOrder Area');
myBinarySearchTree.inOrder(this.show);
this.alterLine('MyBinarySearchTree PostOrder Area');
myBinarySearchTree.postOrder(this.show);
}
// 將內容顯示在頁面上
show(content) {
document.body.innerHTML += `${content}<br /><br />`;
}
// 展現分割線
alterLine(title) {
let line = `--------------------${title}----------------------`;
console.log(line);
document.body.innerHTML += `${line}<br /><br />`;
}
}
// 頁面加載完畢
window.onload = function() {
// 執行主函數
new Main();
};
複製代碼
再看二分搜索樹的遍歷
對二分搜索樹前中後這三種順序的遍歷
function traverse(node) {
if (node === null) return;
// 1. 第一個訪問的機會 前
traverse(node.left);
// 2. 第二個訪問的機會 中
traverse(node.right);
// 3. 第三個訪問的機會 後
}
複製代碼
二叉樹前中後序遍歷訪問節點的不一樣