二叉树概念
二叉树是一个层级的数据结构,每一个二叉树都包含头节点或者子节点,并且二叉树的子节点最多是两个,如下几个图都是二叉树
![](https://img.haomeiwen.com/i13805935/45a34e42a1a2d85f.png)
![](https://img.haomeiwen.com/i13805935/e4c9706c9cb69a98.png)
![](https://img.haomeiwen.com/i13805935/6d306f5b19771984.png)
二叉树的性质(基本的二叉树)
- 二叉树必须要有一个头节点
- 二叉树的子节点最多是两个
- 二叉树节点i的左子节点的索引是2i + 1,右子节点的索引是2i + 2
- 二叉树节点i的父节点索引是(i - 1) / 2, 向下取整
- 根节点没有父节点
二叉树的实现
网上的二叉树大多是按照数组的值去判断的,最后形成的二叉树可能是层次很乱的二叉树,但是如果就是想形成一个从左到右依次排列的二叉树的话,那种方法可能不行,除非数组的数据很好,然后自己写了一个弄了一下。
const arr = [4, 2, 3, 5, 7, 1, 6];
const tree = function() {
const CreateNode = function(value, left, right) {
this.value = value;
this.left = left;
this.right = right;
};
let headList = [];
let childList = [];
this.root = null;
this.insert = function(value) {
const dom = new CreateNode(value, null, null); // 根节点的左右节点都是null
// 判断有没有根节点,没有的话设置根节点
if (!this.root) {
this.root = dom;
headList.push(this.root);
return;
}
if (headList.length * 2 === childList.length) {
headList = childList;
childList = [];
}
for (let i = 0; i < headList.length; i++) {
if (!headList[i].left) {
headList[i].left = dom;
childList.push(dom);
return;
}
if (!headList[i].right) {
headList[i].right = dom;
childList.push(dom);
return;
}
}
};
};
const twoTree = new tree();
arr.forEach(item => {
twoTree.insert(item);
});
console.log(twoTree);
二叉树遍历
说到二叉树我们经常会提到的是二叉树的遍历,二叉树的遍历分为前序遍历,中序遍历,后序遍历和层次遍历,我们依次说明一下这几种情况,需要注意的是,如果遍历到对应节点时候,如果改节点有子节点,需要先让该节点和子节点重复以上动作,下面就用这个二叉树为例,分别写入前中后序遍历
![](https://img.haomeiwen.com/i13805935/a6070bb1c1950a58.png)
前序遍历
前序遍历是先中,在左,在右的过程如果把上面的数组用前序遍历的话就是4, 2, 5, 7,3, 1, 6,递归遍历代码如下
// 前序遍历
function prevTraverse(node) {
if (node === null) return;
console.log(node.value);
prevTraverse(node.left);
prevTraverse(node.right);
}
// twoTree 接上面的代码
prevTraverse(twoTree.root);
这是递归的方式,如果用非递归的方式怎么做了,这里根据牛客网左神的视频,总结一下思路
注意以下节点都是以节点值为名称称呼节点,如节点4就是表示节点值为4的节点,也就是上图根节点
1:新建一个栈,把节点为4的节点(此时这里是根节点)放入栈中
2:抛出节点4,然后把节点4的右子节点先压入栈中,在把左子节点压入栈中
3:重复步骤2,直到栈中没有值,抛出来的值就是先序遍历
中序遍历
中序遍历是先左,在中,在右,按照上面的例子中序遍历的结果就是5,2,7,4,1,3,6,递归代码如下
// 中序遍历
function middleTraverse(node) {
if (node === null) return;
middleTraverse(node.left);
console.log(node.value);
middleTraverse(node.right);
}
middleTraverse(twoTree.root);
这是递归的方式,如果是非递归的怎么办了,一样提供思路
1:定义一个栈和一个变量cur,把节点4也就是根节点压入栈中,并设置cur等于根节点
2:让cur = cur.left,压入栈中
3:重复步骤二直到cur===null,然后抛出节点node,设置cur=node.right,压入栈中重复步骤二
4:直到栈空,抛出来的值就是中序遍历
后序遍历
后续遍历是先左,在右,在中,用上面的例子来说就是5,7,2,1.6.3,4,递归代码如下
function lastTraverse(node) {
if (node === null) return;
lastTraverse(node.left);
lastTraverse(node.right);
console.log(node.value);
}
lastTraverse(twoTree.root);
这是递归的方式,如果是非递归的方式怎么办,思路如下
1:定义两个栈,一个栈名为s1,另一个栈名为s2,把节点4(根节点)放入栈s1中
2:抛出s1的节点放入s2中,并且把s1抛出节点的左子节点先压入s1,右子节点后压入s1
3:重复步骤二,直到s1的栈为空
4:s2依次抛出就是后续遍历
二叉树的相关引申
满二叉树
满二叉树的概念是最后一层是叶子节点,非叶子节点的左右两个孩子要全
![](https://img.haomeiwen.com/i13805935/1e0e5eeff589811e.png)
完全二叉树
完全二叉树的概念是该树中最大的满二叉树的下一层从左到右依次填满(意思先找到该树种的最大的满二叉树)
![](https://img.haomeiwen.com/i13805935/bf0c78f27f4930bf.png)
平衡二叉树
-
平衡二叉树的概念是
1:空树是平衡二叉树
2:非空二叉树,所有的子树的左子树和右子树的高度差为不超过1
image.png
搜索二叉树
搜索二叉树的概念是:任意节点的都比所有左子树的值要大,比右边的要小
![](https://img.haomeiwen.com/i13805935/115c0585a5e3c7d2.png)
红黑树,B-树和B+树有点复杂这里推荐程序员小灰的公众号里面的文章,写的比较好,可以参考下
红黑树:https://zhuanlan.zhihu.com/p/31805309
B-树:https://zhuanlan.zhihu.com/p/54084335
B+树:https://zhuanlan.zhihu.com/p/54102723
网友评论