1简介
- 程序= 算法+ 数据结构
- 数据结构为算法提供服务 , 算法围绕数据结构操作
2复杂度
时间复杂度
就是看代码执行了多少次 , 两个不同的时间复杂度相加 , o(1)+o(n)=o(n),结果等于大的复杂度
例如 : for 为o(n) 嵌套for为 o(n2) o(logN)
空间复杂度
代码所占用内存 ,就是声明了多少个变量. 如果为数组,要里面的每个值都要计算进去
3栈
后进先出, 用push pop可模拟
vscode自带node调试 , 执行代码可以不用放到html里面 , 打个断点按f5, 可显示每个变量的值
栈的应用
10进制转二进制
括号是否闭合 (越靠后的括号,对应的反括号越前) ((((()))))
leetcode 20
函数调用(后面的函数, 先执行)
callstack 调用堆栈, 函数按执行顺序进入callstack
4队列
先进先出,就跟排队一样
应用场景
排队
js异步任务队列
计算最近请求次数 : 计算3000ms内的请求次数
LeetCode 933
任务队列
js刚执行时, 会丢一个匿名事件到任务队列 , js引擎就执行, 当遇到异步, 会把它交给webapi处理, js引擎依然向后执行 . 当异步的回调有事件 , 会将它放到任务队列 , 以此循环
总结
先进先出 , js以数组模拟队列, 队列常用操作 , push shift queue[0]
5 链表
多个元素组成的列表 , 元素存储不连续 , 用next指针链接在一起
与数组的区别
数组插入删除元素,会移动其他元素位置
链表秩序改变next指向就可以了
js没有链表 , 可用object来模拟链表
a = {v=1 }
b = {v=2 }
c = {v=13 }
a.next = b b.next = c
//就形成了一个嵌套结构 , 可以称a 为链表
//遍历链表
var p =a
while(p){
console.log(p.v)
p = p.next
}
//插入值
x = {v = 77}
b.next = x x.next = c
//删除值
b.next = c
LeetCode 237 206 2 83 141
js中的原型链
原型链本质是链表 , 以Object构造函数开头的链表
如果A延着原型链能找到B.protyoe , 则A instanceof B 为true
如果A没有x属性 , 会沿着原型链上往上找
面试题1 instanceof原理
const arr = []
//遍历链表
const instanceof = funrion(a,b){
let p=a
while(p){
if(p===b.prototype) {
return true
}
p = p._prote_
}
return false
}
遍历链表:使用链表指针获取json节点值
6,集合
唯一且无序 , 相当于数组的升级版
es6的set就是集合
集合 的常用操作 :去重 判断元素是否在集合中 求交集
//去重
let arr = [1,2,3,3]
arr= [...new set(arr)]
//判断是否在集合中
let set = new set(arr)
set.has(3)
//求交集
const set2 = new set([2,3])
const jiaoji = new set([...set].filter(item=>{st2.has(item)}))
leetcode 349
es6 set的用法
set类似数组 , 没有重复
使用set对象 :new add delete has size
迭代set :多种迭代方法 , set和array互转 , 求交集\差集
let set = new set()
set.add()
set.delete()
set.has()
set.size
//迭代 key和value是一样的
for(let item in set)
for(let item in set.key())
for(let item in set.value())
for(let [key,value] in set.entries())
//set和array互转
arr= [...set] arr = Array.form(Set)
set = new set(arr)
//交并集
const jiaoji = new set([...set].filter(item=>{st2.has(item)}))
const bingji = new set([...set].filter(item=>{!st2.has(item)}))
7字典
字典也是不重复的数据结构 , 以键值对存储 , 相当于对象的升级版
es6中 为map
常用操作: 增删改查
let m = new map()
//增 m.set('name','小计')
//删 m.delete('name')
m.clear()
//改 m.set('name','小三')
//插 m.get('name')
leetcode 349 20 1 3 76
8树
1种分层的数据模型
前端 :dom , 级联选择器
js中以Object和Array 来构建树
常用操作 : 深度\广度遍历树 , 先中后序遍历
深度优先遍历
先往深处遍历,
算法口诀
先访问根节点
在递归children, 对跟节点的children挨个进行深度优先遍历
广度优先遍历
先遍历上层,一层一层遍历
算法口诀
新建一对列, 把根节点
const root = {
val:1 ,
children:[{
val:2
},{
val:3
}
]
}
//深度优先遍历
const dif = (root)=>{
console.log(root.val)
//root.children.forEach(item=>dif(item))
//简化 root.children.forEach(dif)
}
//广度优先遍历
const bfs = (root)=>{
let p = [root],
while(p.length>0){
let a= p.shift()
console.log(a)
a.children.forEach(item=>p.push(item))
}
}
二叉树
最多只有两个节点
以Object模拟
遍历
先序 根 左子树先序 右子树先序
中序 左子树中序 根 右子树中序
后序 左子树后序 右子树后序 根
//二叉树
obj = {
val=1,
left:{
val=2
}
right:{
val=3
}
}
//先序
let preorder = (obj)=>{
if(!obj) return
console.log(obj.val)
preorder(obj.left)
preorder(obj.right)
}
//中序
let preorder = (obj)=>{
if(!obj) return
preorder(obj.left)
console.log(obj.val)
preorder(obj.right)
}
//后序
let preorder = (obj)=>{
if(!obj) return
preorder(obj.left)
preorder(obj.right)
console.log(obj.val)
}
非递归版
LeetCode 104 111 102 94 112
遍历json所有节点值
渲染antd的树组件
9图
由边连接的一组节点
js用object和array构建图
图的表示法: 邻接矩阵,邻接表
常用操作:深度优先和广度优先遍历
深度优先
访问根节点
对没有访问过的节点进行深度优先遍历
广度优先
新建队列, 把根节点入队
队头出队并访问
把队头没访问过的相邻节点入队
重复23,直到队列为空
//深度
const t = {
A:[B,C]
C:[B,F]
}
const visied = new Set()
const sd = (index)=>{
console.log(index)
visied.add(index)
t[index].forEach(item=>{
if(!visied.has(item)){
sd(item)
}
})
}
//广度
const visied = new Set()
visied.add(A)
const q = [A]
while(visied.length){
const n = q.shift()
console.log(n)
t[n].forEach(item=>{
if(visied.has(item){
q.push(item)
visied.add(item)
})
})
}
10堆
一种特殊的完全二叉树
所以节点都大于它的子节点(称最大堆), 所以节点都小于他的子节点(最小堆)
js中的堆
以数据形似表示堆
左侧子节点 为 index*2+1
右侧子节点 为 index*2+2
父节点位置 (index-1)/2
堆的应用
堆能高效的找出最大值最小值 , 时间复杂(1)
找出第k个最大值最小值