数据结构
队列,栈,链表,哈希表,树
队列 queue
先进先出的数组 fifo
first in first out
餐厅叫号网页
选用队列作为数据结构,queue.push入队,queue.shift出队
HTML
<head>
<title>队列示例</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<div id="screen"></div>
<div class="actions">
<button id="createNumber">取号</button>
<button id="callNumber">叫号</button>
</div>
<div>
当前号码<span id="newNumber"></span>
</div>
<div>
当前队列<span id="queue"></span>
</div>
<script src="./main.js"></script>
</body>
CSS
#screen{
border: 1px solid black;
width: 200px;
height: 200px;
}
JS
const divScreen = document.querySelector('#screen');
const btnCreateNumber = document.querySelector('#createNumber');
const btnCallNumber = document.querySelector('#callNumber');
const spanNewNumber = document.querySelector('#newNumber');
const spanQueue = document.querySelector('#queue');
let n = 0;
let queue = [];
btnCreateNumber.onclick = () => {
n += 1;
queue.push(n);
//queue.push.call(queue,n);
spanNewNumber.innerText = n;
spanQueue.innerText = JSON.stringify(queue);
};
btnCallNumber.onclick = () => {
if (queue.length === 0) {
return;
}
const m = queue.shift();
//const m = queue.shift.call(queue);
divScreen.innerText = `请${m}号就餐`;
spanQueue.innerText = JSON.stringify(queue);
}
栈 stack
后进先出的数组 lifo
last in first out
压栈出栈的过程就是后入先出
function f1(){let a = 1; return a+f2()}
function f2(){let b = 2; return b+f3()}
function f3(){let c = 3; return c}
f1()
JS函数的调用栈call stack就是一个栈
f1调用了f2,f2又调用了f3,那么f3结束后应该回到f2,f2结束后应该回到f1
压栈是push
弹栈是pop,弹出最上面的,把这个值返回给你
链表 Linked List
一个链一个,用一个地址指向下一个对象
JS原型链
let array = [1,2,3]
array.__proto__ === Array.prototype
Array.prototype.__proto__ ===Object.prototype
从这个角度看JS原型链,就是链表;JS的每个对象就是链表
原型链断开(没有数组的原型了)
array.__proto__=Object.prototype
链表的增删改查
一个节点在JS里用一个对象表示{}
节点有2个属性
data data:value
next next:null 默认值是空
const createList = value => {
return createNode(value);
};
创建链表
const appendList = (list, value) => {
const node = createNode(value);
let x = list;
while (x.next) {
x = x.next;
}
x.next = node;
return node;
}
添加节点
const createNode = value => {
return {
data: value,
next: null
};
};
删除节点
const removeFromList = (list, node) => {
let x = list;
let p = null;
while (x !== node) {
p = x;
x = x.next;
};
p.next = x.next;
};
const travelList = (list, fn) => {
let x = list;
while (x !== null) {
fn(x);
x = x.next;
}
};
const list = createList(10); 创建一个链表,节点内容是10
const node2 = appendList(list, 20); 返回到新增加的节点,给list一个新的值20
双向链表
每个节点有一个previous 指向上一个节点
每一个有指向上一个节点和下一个节点的链表叫双向链表
循环链表
最后一个节点的next指向头节点
哈希表
key value pairs
读取哈希表
假设:哈希表hash里有1万对key-value
例如:name:'frank',age:18`......
如何读取hash['xxx']速度最快
不做任何优化,hash['xxx']需要遍历所有的key
对key排序,使用2分查找
用字符串对应的ASCll数字做索引
对索引做除法,取余数,有冲突就顺延
key越多,读取速度越慢
树 tree
一个链多个,data,children
创建树
const 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 = 0; 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(node2, 201); 新增节点