一、数据结构简介
数据结构是什么
- 就是数据与数据之间关系和结构
如何表示两个数据
如果顺序有意义
-
[x,y]表示第一个是x,第二个是y -
比如坐标就是这样表示的数据
-
要提供
first和last操作
如果顺序没有意义
-
(x,y)和(y,x)一样 -
比如血压值(120,80)和(80,120)表达的意思没区别
-
不需要提供
first和last操作
如何表示N个数据
如果顺序有意义
-
数组表示
[a1,a2,...,aN] -
要提供索引操作
get(i) -
要提供
add/indexOf/delete操作
如果顺序没有意义
-
集合表示
{a1,a2,...,aN} -
要提供
add/delete/has操作
如何表示N对N数据
比如学号
-
用哈希表可以表示
-
hash = {1001 => '小明', 1002 => '小红'} -
key可以是任何数据类型(和js的对象不一样)
数据结构的作用
数据结构 = 数据形式(逻辑形式)+ 操作
-
数据结构在编程世界里或生活中都很常见,可以让人快速理清解决问题的思路
-
面试特别特别爱问
锻炼抽象能力
-
一种数据结构往往可以解决很多类似的问题
-
如果选错了数据结构,那就很难想到思路
-
大佬级别的程序员更重视数据结构,而不是算法
二、队列Queue(先进先出的 FIFO 的数组)
实现一个餐厅叫号网页
-
点击取号,生成一个号码
-
点击叫号,显示xxx号请您就餐
代码思路
-
先选择队列Queue作为数据结构
-
queue.push为入队,queue.shift为出队
代码实现
const 显示屏
const 拿号按钮
const 叫号按钮
const 当前号码显示
const 当前队列显示
let n = 0; // 初始化号码
let 当前队列数组 = [];
拿号按钮.onclick = () => {
n += 1;
// 练习一下call的用法
当前队列数组.push.call(queue, n);
当前号码显示.innerText = n;
当前队列显示.innerText = JSON.stringify(当前队列数组);
};
叫号按钮.onclick = () => {
if (当前队列数组.length === 0) {
alert('没号了叫个屁啊')
return
}
const m = 当前队列数组.shift.call(queue);
显示屏.innerText = `请 ${m} 号就餐`;
当前队列显示.innerText = JSON.stringify(当前队列数组);
};
三、栈 Stack (后进先出 LIFO 的数组)
- JS函数的调用栈call stack 就是一个栈
function f1() {
let a = 1; return a + f2()
}
function f2() {
let b = 2; return b + f3()
}
function f3() {
let c = 3; return c
}
- 假如函数f1调用函数f2,函数f2再调用函数f3,那f3调用完了应该回到f2的位置,f2调用完了回到f1的位置(压栈,弹栈)
四、链表 Linked List (一个链一个)
实际使用
-
let array = [1,2,3] -
array.__proto__ === Array.prototype -
Array.__proto__ === Object.prototype -
这个角度看对象,就是链表
代码实现
list = create(value) 创建链表
const createList = (value) => {
return createNode(value)
}
const createNode = (value) => {
return {
data: value,
next: null
}
}
node = get(index) 获取链表
const getList = (list, index) => {
let x = list
for (let i = 1; i <= index; i++) {
x = x.next
return x
}
}
append(node,value) 插入一个链表
const appendList = (list, value) => {
const node = createNode(value)
while (list.next) { //判断list是否为最后一个节点,如果不是就继续往下找 直到确定是最后一个节点
list = list.next
}
list.next = node
return node
}
trevel(list, fn) 遍历链表
const travelList = (list, fn) => {
let x = list
while (x !== null) { // 判断list是否为null是因为要遍历所有节点 包括最后一个 直到list是最后一个节点的next以后再退出
fn(x)
x = x.next
}
}
remove(node) 删除一个链表
const removeFromList1 = (list, node) => {
let x = list;
let p = node; // 这里不能为null
while (x !== node && x !== null) { // 如果 node 不在 list 中,x 就可能为 null
p = x;
x = x.next;
}
if (x === null) { // 若 x 为 null,则不需要删除,直接 return, false 表示无法删除不在list里的节点
return false
} else if (x === p) { // 这说明要删除的节点是第一个节点
p = x.next
return p // 如果删除的是第一个节点,那么就要把新 list 的头节点 p 返回给外面,即 newList = removeFromList(list, list)
} else {
p.next = x.next;
return list // 如果删除的不是第一个节点,返回原来的 list 即可
}
};
五、哈希表
哈希表是干嘛的
- 声明哈希表是很简单的,存储数据也是很简单的,最难的是如何快速读取数据
场景
-
假设哈希表hash里有一万对key-value
-
比如
name:'jack',age:18,pi:'property',...
使哈希表读取变快的解决方法
-
不做任何优化,
hash['xxx']需要遍历hash表里的所有key,复杂度为:O(n) -
对key排序,使用二分法查找,复杂度为:O(log2n)
-
用字符串对应的ASCII数字做索引,复杂度为:O(1) 需要的空间太大
-
对索引做除法取余数,复杂度为:O(1),如果冲突了就顺延
有一篇文章比较通俗的介绍了这个数据结构「哈希表」是什么?有哪些常用的解决冲突的方法?
六、树 Tree (一个链多个)
实际使用
-
中国的行政区域划分,省-市-区(县)可以看成一棵树
-
公司的层级结构可以看成一棵树
-
网页中的节点可以看成一棵树
代码实现
let tree = createTree(value) 新增树
const createTree = (value) => {
return {
data: value,
children: null,
parent: null,
}
}
let node = addChild(tree,node) 新增节点
const addChild = (node, value) => {
const newNode = {
data: value,
children: null,
parent: node
}
node.children = node.children || []
node.children.push(newNode)
return newNode
}
travel(tree) 遍历节点
const travel = (tree, fn) => {
fn(tree)
if (!tree.children) {
return
}
for (let i = 0; i < tree.children.length; i++) {
travel(tree.children[i], fn)
}
}
find(tree,node) 找到节点
const find = (tree, node) => {
if (tree === node) {
return tree
} else if (tree.children) {
for (let i = 0; i < tree.children.length; i++) {
const result = find(tree.children[i], node)
if (result) {
return result
}
return undefined
}
} else {
return undefined
}
}
removeChild(node1,node2) 删除节点
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)
}