数据结构
数据结构分物理结构和逻辑结构
物理数据结构
数据结构的存储形式有两种:顺序存储和链式存储
逻辑结构
- 集合结构 数据间同属一个集合并无其它关系
- 线性结构 数据之间是一对一的关系
- 图形结构 数据间是多对多的关系
- 树形结构 数据之间存在一对多的层次关系
队列
先进先出
//现实中典型例子的就是叫号了
const currentNumber = document.getElementById('currentNumber')
const callNumber = document.getElementById('callNumber')
const getNumber = document.getElementById('getNumber')
const newNumber = document.getElementById('newNumber')
const queueList = document.getElementById('queueList')
let number = 0
let queue = []
currentNumber.innerText = '还未开始叫号'
getNumber.onclick = () => {
number += 1
queue.push(number)
newNumber.innerText = `${number},前面还有${queue.length - 1}人`//可优化
queueList.innerText = queue.toString()
}
callNumber.onclick = () => {
if (queue.length < 1) {
alert('目前没有用户')
} else {
let current = queue.shift()
currentNumber.innerText = `请${current}号就餐`
queueList.innerText = queue.toString()
}
}
栈
先进后出,顺序存储
//现实中的例子就是电梯了,这里用函数压栈,弹栈的方式解释
function f1(){let a = 1 return a+f2()}
function f2(){let b = 2 return b+f3()}
function f3(){let b = 3 return b}
f1()
还是看图吧
链表
对象与对象之间的指引关系(函数也是对象),无需存储
//通过链表实现节点的增删改查
//创建节点
const createNode = (value) => {
return {
data: value,
nextNode: null
}
}
//添加节点
const appendNode = (node, value) => {
let lastNode = node
while (lastNode.nextNode) {
lastNode = lastNode.nextNode
}
lastNode.nextNode = createNode(value)
return lastNode.nextNode
}
//删除节点
const removeNode = (list, node) => {
let lastNode = list
let parentNode = node
if (!node) { return alert('节点为空') }
while (lastNode !== node) {
parentNode = lastNode
lastNode = lastNode.nextNode
}
if (parentNode === lastNode) {
parentNode = lastNode.nextNode
return parentNode
} else {
parentNode.nextNode = lastNode.nextNode
return lastNode
}
}
//遍历节点
const travel = (list, fn) => {
let lastNode = list
fn(lastNode)
while (lastNode.nextNode) {
lastNode = lastNode.nextNode
fn(lastNode)
}
}
let list = createNode(10)
let node1 = appendNode(list, 20)
let node2 = appendNode(list, 30)
let node3 = appendNode(list, 40)
let node4 = appendNode(list, 50)
let list2 = removeNode(list, list)
console.log(list2)
travel(list, (node) => console.log(node.data))
hash表
key 对应value,key是唯一的,不重复的
也叫散列函数,散列映射
关于解决碰撞(冲突)最常用的是除留余数法
js中的对象是模拟hash表实现的
树形结构
树形结构我们前端应该很熟悉,dom树就是这种类型
一对多的关系,链表的升级版,下面用一个小例子实现节点的增删改查
//创建节点
const createNode = (value, parentNode) => {
return {
node: value,
children: null,
parent: parentNode || null
}
}
//添加节点
const appendChildren = (tree, value) => {
let newNode = createNode(value, tree)
tree.children = tree.children || []
tree.children.push(newNode)
return newNode
}
//删除节点
const removeChildren = (tree, node) => {
if (tree == node) {
alert('你删根节点还用这么费劲?')
}
for (let i in tree.children) {
if (tree.children[i] !== node) {
removeChildren(tree.children[i], node)
} else {
tree.children.splice(i, 1)
}
}
return tree
}
//遍历节点
const travel = (node, fn) => {
fn(node)
for (let i in node.children) {
if (node.children[i]) {
travel(node.children[i], fn)
}
}
}
let tree = createNode(10)
let node2 = appendChildren(tree, 20)
let node3 = appendChildren(tree, 30)
let node2_1 = appendChildren(node2, 201)
let node2_2 = appendChildren(node2, 202)
let node3_2 = appendChildren(node3, 302)
let node3_3 = appendChildren(node3, 303)
removeChildren(node3, node3_2)
travel(tree, (tree) => console.log(tree.node))
什么是算法
将一个小故事吧,高斯算法
高斯小时候非常淘气,一次数学课上,老师为了让他们安静下来,给他们列了一道很难的算式,让他们一个小时内算出1+2+3+4+5+6+……+100的得数。全班只有高斯用了不到20分钟给出了答案,因为他想到了用(1+100)+(2+99)+(3+98)……+(50+51)……一共有50个101,所以50×101就是1加到一百的得数。后来人们把这种简便算法称作高斯算法。
//我们重复计算1+2+3+4+5....100
let number = 1
for (let i = 1; i < 100; i++) {
console.log(i)
number += i + 1
}//这种算法 随着数字的增大,计算次数也会增加
console.log(number)
//高斯算法发现每个数之间的规律 1+100 =101 2+99=101 3+98 =101
result = (100 / 2) * 101//用这种方法 无论数字有多大,我们只用计算一次
console.log(result)
//从事物之间的关系找到规律,找到最合适的算法
算法的五个基本特征
输入 具有零个或多个输入
输出 具有一个或多个输出
有穷性 自动结束,不会无限循环
可行性 每一个步骤都是可行的
确定性 每一个步骤都有确定的含义,不会出现二义性