樹形結構 {ignore}
[toc]
樹
樹是一個類似於連結串列的二維結構,每個節點可以指向0個或多個其他節點
樹具有以下特點:- 單根:如果一個節點A指向了另一個節點B,僅能通過A直接找到B節點,不可能通過其他節點直接找到B節點
- 無環:節點的指向不能形成環
樹的術語:
- 結點的度:某個節點的度 = 該節點子節點的數量
- 樹的度:一棵樹中,最大的節點的度為該樹的度
- 結點的層:從根開始定義起,根為第1層,根的子結點為第2層,以此類推;
- 樹的高度或深度:樹中結點的最大層次
- 葉子節點:度為0的結點稱為葉結點;
- 分支節點:非葉子節點
- 子節點、父節點:相對概念,如果A節點有一個子節點B,則A是B的父節點,B是A的子節點
- 兄弟節點:如果兩個節點有同一個父節點,則它們互為兄弟節點
- 祖先節點:某個節點的祖先節點,是從樹的根到該節點本身經過的所有節點
- 後代節點:如果A是B的祖先節點,B則是A的後代節點
樹的程式碼表示法:
// 樹的程式碼表示法
function Node(value){
this.value = value; //儲存資料
this.children = []; //用陣列來表示子節點
}
var a = new Node("a");
var b = new Node("b");
var c = new Node("c");
var d = new Node("d");
var e = new Node("e");
a.children.push(b,e);
b.children.push(c,e);
console.log(a);
複製程式碼
二叉樹
如果一顆樹的度為2,則該樹是二叉樹
二叉樹可以用下面的程式碼表示
function Node(value){
this.value = value;
this.left = null;
this.right = null;
}
複製程式碼
二叉樹的相關演算法
編寫各種函式,實現下面的功能
- 對二叉樹遍歷列印
- 前(先)序遍歷 DLR
- 中序遍歷 LDR
- 後序遍歷 LRD
- 根據前序遍歷和中序遍歷結果,得到一顆二叉樹
- 計算樹的深度
- 查詢二叉樹
- 深度優先 Depth First Search
- 廣度優先 Breadth First Search
- 比較兩棵二叉樹,得到比較的結果
function Node(value) {
this.value = value;
this.left = null;
this.right = null;
}
/**
* 前序遍歷
* @param {*} root
*/
function DLR(root) {
if (!root) return;// 沒有節點
console.log(root.value);
DLR(root.left);
DLR(root.right);
}
/**
* 中序遍歷
* @param {*} root
*/
function LDR(root) {
if (!root) return;// 沒有節點
LDR(root.left);
console.log(root.value);
LDR(root.right);
}
/**
* 後序遍歷
* @param {*} root
*/
function LRD(root) {
if (!root) return;// 沒有節點
LRD(root.left);
LRD(root.right);
console.log(root.value);
}
/**
* 根據前序遍歷,和 中序遍歷,得到一棵樹的根節點
* @param {*} dlr
* @param {*} ldr
*/
function getTree(dlr, ldr) {
dlr = dlr.split("");
ldr = ldr.split("");
if (dlr.length !== ldr.length) throw new Error("無效的遍歷值");
if (dlr.length === 0) return null;
var rootValue = dlr[0]; //取出根節點的值
var root = new Node(rootValue);
var index = ldr.indexOf(rootValue); //找到根節點的值在中序遍歷中的位置
var leftLDR = ldr.slice(0, index).join(""); //左邊的中序遍歷結果
var leftDLR = dlr.slice(1, leftLDR.length + 1).join(""); //左邊的前序遍歷結果
root.left = getTree(leftDLR, leftLDR);
var rightLDR = ldr.slice(index + 1).join(""); //右邊的中序遍歷結果
var rightDLR = dlr.slice(leftLDR.length + 1).join(""); //右邊的前序遍歷結果
root.right = getTree(rightDLR, rightLDR);
return root;
}
/**
* 得到一棵樹的深度
* @param {*} root
*/
function getDeep(root) {
if (!root) return 0;
var left = getDeep(root.left);
var right = getDeep(root.right);
return Math.max(left, right) + 1;
}
var root = getTree("abcde", "cbdae")
console.log(root)
console.log(getDeep(root));
// var a = new Node("a");
// var b = new Node("b");
// var c = new Node("c");
// var d = new Node("d");
// var e = new Node("e");
// var f = new Node("f");
// a.left = b;
// a.right = e;
// b.left = c;
// b.right = d;
// e.left = f;
// LRD(a);
複製程式碼