2024年最全二叉树的实现、遍历及面试题,2024年最新被面试官怼

React

  • 介绍一下react

  • React单项数据流

  • react生命周期函数和react组件的生命周期

  • react和Vue的原理,区别,亮点,作用

  • reactJs的组件交流

  • 有了解过react的虚拟DOM吗,虚拟DOM是怎么对比的呢

  • 项目里用到了react,为什么要选择react,react有哪些好处

  • 怎么获取真正的dom

  • 选择react的原因

  • react的生命周期函数

  • setState之后的流程

  • react高阶组件知道吗?

  • React的jsx,函数式编程

  • react的组件是通过什么去判断是否刷新的

  • 如何配置React-Router

  • 路由的动态加载模块

  • Redux中间件是什么东西,接受几个参数

  • redux请求中间件如何处理并发

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

一个炒鸡简单的二叉搜索树就写好了,写的简单是为了方便写二叉搜索树的遍历。二叉树的遍历方式有**「深度优先遍历和广度优先遍历」两种思路。深度优先遍历又分为「先序遍历、中序遍历、后序遍历」三种方式;广度优先遍历主要是「层次遍历」**。

先序遍历顺序:根、左、右

中序遍历顺序:左、根、右

后序遍历顺序:左、右、根

二叉树的遍历

如图所示的二叉树的遍历结果分别为:

先序遍历结果:F B A D C E G I H

中序遍历结果:A B C D E F G H I

后序遍历结果:A C E D B H I G F

层次遍历结果:F B G A D I C E H

二叉树的遍历


递归遍历的代码非常简单:

// 先序遍历的顺序:根节点、左节点、右节点

// 先序遍历可以打印出树的结构

root = this.root

DLR(root) {

if(root) {

console.(root.value)

this.DLR(root.left)

this.DLR(root.right)

}

}

// 中序遍历顺序:左节点、根节点、右节点

// 二叉搜索树的中序遍历结果得到的就是有序的值

LDR(root) {

if(root) {

this.LDR(root.left)

console.log(root.value)

this.LDR(root.right)

}

}

// 后序遍历顺序:左节点、右节点、根节点

// 后序遍历可以用于从叶子节点向根节点访问

LRD(root) {

if(root) {

this.LRD(root.left)

this.LRD(root.right)

console.log(root.value)

}

}

非递归遍历比递归遍历要复杂,我们需要借助到栈这种数据结构。

栈的特点是先进后出,所以我们可以**「将后处理的节点先进栈,先处理的节点后进栈」**。

root = this.root

// 先序遍历的顺序是根左右,所以先入栈右节点,再入栈左节点

Dlr() {

if(!root) return null

let s = new Stack()

s.push(root)

while(s.getCount()) {

node = s.pop()

console.log(node.value)

if(node.right) {

s.push(node.right)

}

if(node.left) {

s.push(node.left)

}

}

}

// 中序遍历顺序是左根右,先将根节点和所有的左节点入栈

LDR() {

if(!node) return null

let s = new Stack()

s.push(root)

while(s.getCount()) {

if(root) {

s.push(root)

root = root.left

}

node = s.pop()

console.log(node.value)

// 如果出栈的节点存在右子树,将该子树的所有左节点入栈

root = node.right()

}

}

// 由于左右节点没有直接的访问方法,所以先入栈右子树,然后入栈左子树,将得到的结果数组翻转

Lrd(){

if(!root) return null

let s = new Stack()

let res = []

s.push(root)

while(s.getCount()){

node = s.pop()

res.push(node.value)

if(node.left) s.push(node.left)

if(node.right) s.push(node.right)

}

return res.reverse()

}

接下来就是层次遍历,层次遍历也需要借助到别的数据结构,这里使用队列实现。

BFS() {

if (!this.root) return null

let q = new Queue()

q.enqueue(this.root)

while (!q.isEmpty()) {

let n = q.deQueue()

console.log(n.value)

if (n.left) q.enQueue(n.left)

if (n.right) q.enQueue(n.right)

}

}

层次遍历的思路是**「将一个节点出栈的同时,将它的左节点和右节点入栈」**。队列先进先出的特点可以保证一层的节点遍历完再遍历下一层的节点。

二叉树的其他操作


「获取最大或最小值」。由于二叉搜索树的特性,小值在左子树,大值在右子树,所以我们只需要比较当前节点的值,就知道向左还是向右遍历。找最小值一直向左遍历,最大值一直向右遍历。

root = this.root

getMin() {

return this._getMin(root).value

}

_getMin(node) {

if(!node.left) return node

return this.getMin(node.left)

}

getMax() {

return this._getMax(root).value

}

_getMax(node) {

if(!node.left) return node.value

return this.getMax(node.right)

}

「第n大的值」。二叉搜索树由于只能从根节点往子节点遍历,所以我们没办法直接获取到节点的排名。所以我们需要对二叉树的定义改一下,为每一个节点添加一个size属性,直接标明该节点前有多少节点,为了方便计算,包含自身。

class Node{

constructor(value) {

this.value = value

this.left = null

this.right= null

this.size = 1

}

_getSize(node) {

return node ? node.size : 0

}

addChild(node, v) {

if (!node) return new Node(v)

// 节点下插入一个子节点时,该节点的size+1

if (node.value > v) {

node.size++

node.left = this.addChild(node.left, v)

} else if (node.value < v) {

node.size++

node.right = this.addChild(node.right, v)

}

return node

}

select(k) {

let node = this._select(this.root, k)

return node ? node.value : null

}

_select(node, k) {

if (!node) return null

// 先获取根节点的左子树的size,如果k小于size,就在左子树查找,如果k大于size就在右子树寻找

let size = node.left ? node.left.size : 0

if (size > k) return this._select(node.left, k)

// 在右子树的情况下,减去左子树和根节点,问题就变成在右子树中,第(k - size - 1)个节点

if (size < k) return this._select(node.right, k - size - 1)

return node

}

}

「删除节点」。在二叉树上删除一个节点是一个复杂的操作,首先要分多种情况考虑,其次删除节点后,还要保证二叉搜索树的特性。删除节点有三种情况:

  • 没有子节点

  • 有一条子树

  • 有两条子树

第一种情况很好操作,只需要判断没有子节点就可以直接删除。

第二种情况也好操作,只需要将子树再接上去就可以。

前端框架

前端框架太多了,真的学不动了,别慌,其实对于前端的三大马车,Angular、React、Vue 只要把其中一种框架学明白,底层原理实现,其他两个学起来不会很吃力,这也取决于你以后就职的公司要求你会哪一个框架了,当然,会的越多越好,但是往往每个人的时间是有限的,对于自学的学生,或者即将面试找工作的人,当然要选择一门框架深挖原理。

以 Vue 为例,我整理了如下的面试题。

Vue部分截图

如果你觉得对你有帮助,可以戳这里获取:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

  • 30
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值