这是我参与2022首次更文挑战的第28天,活动详情查看:2022首次更文挑战」。
我个人觉得要想进大厂,就必须学习了解算法和数据结构,经历了多次面试之后,也知道了算法和数据结构的重要性,所以,我也打算从今天开始,进入学习,下载了一下电子书,边看书,边跟着书的例子来敲一下代码,下面就开始总结一下对算法和数据结构的学习吧。
第二十八天:继续学习树
向二叉搜索树中插入一个键
insert(key) {
if(this.root === null) {
this.root = new Node(key)
}else {
this.insertNode(this.root, key)
}
}
如果根节点没值的话,直接创建一个节点实例赋值给根节点,否则利用辅助方法插入节点到已经有值的树中。
下面实现它的辅助方法
insertNode(node, key) {
if(this.compareFn(node.key, key) === Compare.LESS_THAN) {
if(node.left === null) {
node.left = new Node(key)
}else {
this.insertNode(node.left, key)
}
}else {
if(node.right === null) {
node.right = new Node(key)
}else {
this.insertNode(node.right, key)
}
}
}
首先判断一下当前节点的值和传入的值谁大,如果当前值比传入的值小,那么就应该插入左侧,再判断左侧现在有没有值,没有的话直接插入一个新的节点,有的话,递归走当前辅助方法插入。如果当前值比传入的值大,就应该插入右侧,判断和左侧的基本一样,如果右侧没有值,直接插入一个节点,有值的话,递归辅助方法插入。
树的遍历
树的遍历有几种方案:中序遍历、先序遍历和后序遍历。
中序遍历
中序遍历是一种以上行顺序访问BST所有节点的遍历方式,从最小到最大的顺序访问所有节点。
inOrderTraverser(callback) {
this.inOrderTraverserNode(this.root, callback)
}
遍历方法接收一个回调,回调函数用来定义我们对遍历到的每个节点进行操作。
inOrderTraverserNode(node, callback) {
if(node !== null) {
this.inOrderTraverserNode(node.left, callback)
callback(node.key)
this.inOrderTraverserNode(node.right, callback)
}
}
跳用这个辅助方法的时候,我们在上面传入的参数是root,从根节点开始遍历,然后如果当前的节点不为空,就递归左侧,然后执行回调函数,然后如果左侧的值遍历完了,就回到上一层遍历右侧,如果右侧的值也为null,继续回到上一层。下面的图可以清晰的看到遍历过程
遍历出来的数据是:3 5 6 7 8 9 10 11 12 13 14 15 18 20 25,可以看出它是从小到大排序的
先序遍历
先序遍历是以优先于后代节点的顺序访问每个节点的
preOrderTraverse(callback) {
this.preOrderTraverseNode(this.root, callback);
}
上面和中序遍历一样,我们需要实现这个辅助函数
preOrderTraverseNode(node, callback) {
if (node != null) {
callback(node.key);
this.preOrderTraverseNode(node.left, callback);
this.preOrderTraverseNode(node.right, callback);
} }
和上面的中序遍历其实差不多,不一样的是,这次我们先在递归左侧前处理了这个节点的值,每当进入递归,就先打印出这个值,然后走递归,当左侧递归走完之后就会走右侧递归,然后一层层的往上走。下面的图清晰的知道路径
所以输出的值是:11、7、5、3、6、9、8、10、15、13、12、14、20、18、25
后序遍历
后序遍历是先访问节点的后代节点,在访问节点本身
postOrderTraverse(callback) {
this.postOrderTraverseNode(this.root, callback);
}
后序遍历也和之前的一样,不同的是辅助函数
postOrderTraverseNode(node, callback) {
if (node != null) {
this.postOrderTraverseNode(node.left, callback);
this.postOrderTraverseNode(node.right, callback);
callback(node.key);
} }
后序遍历是先把左右遍历都走完,在对数据进行操作,可以看到上面,先访问左侧子节点,然后是右侧子节点,最后才是父几点。下图可以清晰的看到过程。