树形结构 {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);