口语化,方便记忆
队列queue
先进先出的数据结构
可用数组的push
和shift
方法实现
push
方法将元素加入到数组末尾
shift
方法将第一个元素删除
栈Stack
后进先出的数据结构
可用数组的push
和pop
方法实现
pop
方法将最后一个元素删除
js函数调用栈就是一个栈
比如:
function f1(){let a=1 ;return a+f2()}
function f2(){let b=2;return b+f3()}
function f3(){let c=3;return c}
f1()
执行过程是
- 函数定义先忽略,直到f1()调用
- 将
f1()
添加进调用栈
- 调用栈
f1()
- 执行
f1()
中的代码,碰到f2()
,将f2()
添加进调用栈
- 调用栈
f2()
f1()
- 执行
f2()
中的代码,碰到f3()
,将f3()
添加进调用栈
- 调用栈
f3()
f2()
f1()
- 执行
f3()
中的代码,没有函数,直接执行完毕,f3()
弹栈
- 调用栈
f2()
f1()
- 接着继续执行
f2()
中的代码,f3
返回了3,f2
中的代码执行完毕,f2
弹栈
- 调用栈
f1()
- 继续执行
f1()
中的代码,f2
返回了5,f1
中代码执行完毕,f1()
弹栈,执行结束
链表
一个接着一个数据结构
原型链的实现就是链表,实例上保存着指向原型的地址,实例的原型上又存在原型的地址,形成一个链表结构
要删除一个节点,只要把上一个节点的next指向下一个节点就行
链表的增删改查
const createList=value=>{
return createNode(value)
}
const appendList=(list,value)=>{
const node = createNode(value)
while (list.next) {
list=list.next
}
list.next=node
return node
}
const removeFromList = (list, node) => {
let previous=node
while (list !== node&&list!==null) {
//这里的p始终是上一个节点
previous = list
//list最终会是要删的那个节点
list=list.next
}
if (list === null) {
return
} else if (list === previous) {
previous = list.next
return previous
} else {
previous.next = list.next
return list
}
}
const createNode=value=>{
return{
data:value,
next:null
}
}
const travelList = (list,fn) => {
while (list!==null) {
fn(list)
list=list.next
}
}
const list=createList(10)
const node1=appendList(list,20)
const node2=appendList(list,30)
console.log(list)
travelList(list, node => {
console.log(node.data)
})
let x=list
const newList=removeFromList(list, x)
console.log(newList)
哈希表
键值对
- 不做任何优化,hash['xxx']需要遍历所有key,O(n)
- 对key排序,使用二分查找,O(log2 n)
- 用字符串对应的ACSII数字做索引,O(1)
- 对索引做除法取余数,O(1),冲突就顺延
树
相比链表是一个接一个,树是一个接多个
如网页中的节点,就是一棵树
实现一下增删改查
let createTree = (value) => {
return {
data: value,
children: null,
parent:null
}
}
const addChild = (node,value) => {
const newNode = {
data: value,
children: null,
parent:node
}
node.children = node.children || []
node.children.push(newNode)
return newNode
}
const travel = (tree, fn) => {
fn(tree)
if (!tree.children) {
return
}
for (let i = 0; i < tree.children.length; i++){
travel(tree.children[i],fn)
}
}
const removeNode = (tree, node) => {
const siblings = node.parent.children
let index = 0
for (let i = 1; i < siblings.length; i++){
if (siblings[i] === node) {
index=i
}
}
siblings.splice(index,1)
}
const tree = createTree(10)
const node2 = addChild(tree, 20)
addChild(tree, 30)
addChild(tree, 40)
const node5=addChild(tree, 50)
addChild(node2, 201)
addChild(node2, 202)
addChild(node2,203)
console.log(tree)
travel(tree, node => {
console.log(node.data)
})
removeNode(tree, node5)
console.log(tree)