树
概念:
- 拥有相同的父节点的节点,互称为兄弟节点
- 节点的深度:从根节点到该节点所经历的边的个数
- 节点的高度:节点到叶节点的最长路径
- 树的高度:根节点的高度
二叉树
二叉树即最多仅有两个子节点的树
二叉树的存储方法:
- 链式存储(即用链表存储)
- 线性存储(即用数组存储)
二叉树常见类型
完全二叉树:如果对满二叉树的结点进行编号, 约定编号从根结点起, 自上而下, 自左而右。则深度为k的, 有n个结点的二叉树, 当且仅当其每一个结点都与深度为k的满二叉树中编号从1至n的结点一一对应时, 称之为完全二叉树。
满二叉树:一棵深度为k且有(2的k次方 - 1)个结点的二叉树称为满二叉树。即除了叶结点外每一个结点都有左右子叶且叶子结点都处在最底层的二叉树
注意:满二叉树一定是完全二叉树,完全二叉树不一定是满二叉树
平衡二叉树:二叉树中,每一个节点的左右子树的高度相差不能大于 1,称为平衡二叉树。即上面两张都可以为平衡二叉树。
二叉搜索树(二叉排序树): 二叉搜索树具有以下性质:若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉搜索树。
实现一棵二叉搜索树
function Tree(){
//初始根节点为null
this.root = null;
//该构造函数为节点
function Node(val) {
this.val = val;
this.left = null;
this.right = null;
}
//该方法用于插入,传入的是值
this.insert(val) {
//需要将值转化为节点
let newNode = new Node(val);
if(this.root === null) {
this.root = newNode;
}else {
insertNode(this.root, newNode);
}
}
//该函数用于插入到节点里
//这里的方法可以自己编写按照各种二叉树
//我这是按照二叉搜索树概念进行
function insertNode(node, newNode) {
if(node.val > newNode.val) {
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);
}
}
}
}
//------------------进行测试
let a = new Tree();
a.insert(10);
a.insert(7);
a.insert(11);
a.insert(5);
a.insert(6);
a.insert(8);
a.insert(12);
console.log(a);
结果:
二叉树的遍历
深度优先遍历
- 前序遍历(中左右)
- 中序遍历(左中右)
- 后序遍历(左右中)
示例:以实现的二叉树代码进行编写
前序遍历:10,7,5,6,8,11,12(自己心算结果)
this.preErgodic = ()=>{
//res存储遍历结果
let res = [];
function preErgodicTree(root) {
if(root !== null) {
res.push(root.val);
preErgodicTree(root.left);
preErgodicTree(root.right);
}
}
preErgodicTree(this.root);
return res;
}
//-----------------输出到控制台
console.log(a.preErgodic());
结果: (7) [10, 7, 5, 6, 8, 11, 12]
图看不到不好算,嘿嘿嘿,放下来好看点
中序遍历:5,6,7,8,10,11,12(自己心算结果)
this.inOrderErgodic = () => {
//res存储遍历结果
let res = [];
function inOrderErgodicTree(root) {
if (root !== null) {
inOrderErgodicTree(root.left);
res.push