| 常用数据结构
- 数组(Array)
- 栈(Stack)先进后出 (LIFO)
- 队列(Queue)先进先出(FIFO)
- 链表(Linked List)
- 树(Tree)
- 图(Graph)
- 堆(Heap)
- 散列表(Hash 哈希表)
如果数据结构中的项目按顺序存储,我们就说数据结构是“线性的”。
数组、链表和堆栈都是线性数据结构。
栈
栈存储数据的方式跟数组一样,都是将元素排成一行。只不过它还有以下3条约束。
- 只能在末尾插入数据
- 只能读取末尾的数据
- 只能移除末尾的数据
队列
你可以将队列想象成是电影院排队。排在最前面的人会最先离队进入影院。
因此计算机科学家都用缩写“FIFO”(first in, first out)先进先出,来形容它。
与栈类似,队列也有3个限制(但内容不同)。
- 只能在末尾插入数据(这跟栈一样)
- 只能读取开头的数据(这跟栈相反)
- 只能移除开头的数据(这也跟栈相反)
| js中的数据结构
javaScript中,数据类型分为基本数据类型和引用数据类型,
栈内存
基本数据类型七种包含:null、undefined、string、number、boolean、symbol、bigint
这七种数据类型存储在栈空间,我们按值访问。
基本类型都存储在栈内存中,是大小固定并且有序的
栈很少用于需要长期保留数据的场景,却常用于各种处理临时数据的算法。
计算机是用栈来记录每个调用中的函数。这个栈就叫作调用栈。
堆内存
一般由操作人员(程序员)分配释放,若操作人员不分配释放,将由OS(操作系统)回收释放。
分配方式类似链表。
堆存储在二级缓存中。
JavaScript 使用堆内存的 Object 类型,它包含:
- Object
- Function
- Array
- Date
- RegExp
栈和堆的区别
- 空间分配不同
栈由系统自动分配释放堆由程序员分配释放
- 缓存方式不同
栈是一级缓存,存取速度快,不灵活
堆是二级缓存,存取速度慢,较灵活
实现
- js实现入栈和出栈
let stackArr = []
// 入栈
stackArr.push(something)
// 出栈
stackArr.pop()
😂😂
- js实现队列
let queueArr = []
// 入列
queueArr.push(something)
// 出列
queueArr.shift()
🙈
栈的应用
递归
递归十分适用于那些无法预估计算深度的问题,如对象的深拷贝、文件系统遍历
改用递归并不会改变算法的大O
递归之于阶乘
const factorial = (num)=> {
if (num <= 1) return num;
return factorial(num - 1) * num;
}
递归之于快排
快速排序(Quicksort),又称划分交换排序(partition-exchange sort),简称快排,是一种效率很高的排序算法。
快速排序是不稳定的排序方法
当数组是完全无序时, 时间复杂度最低,为O(nlog2n)
当数组完全有序时,时间复杂度最高,为O(n^2)
快速排序严重依赖于分区
利用递归实现快排
- 拿出一个中间数来分区
- 遍历判断值在左或右并存入数组
- 继续递归左右数组并合并,记得合并中间数
- 返回合并结果
const quickSort = arr => {
if (arr.length <= 1) return arr;
let center = arr.shift(), // 拿出一个中间数
leftArr = [],
rightArr = [],
result = [];
// 遍历判断值在左或右并存入数组
for (let i = 0;i <=arr.length; i++) {
arr[i] <= center && leftArr.push(arr[i]);
arr[i] > center && rightArr.push(arr[i]);
}
result = quickSort(leftArr).concat(center, quickSort(rightArr)); // 继续递归左右数组并合并,记得合并中间数
return result;
}
队列的应用
队列应用广泛,从打印机的作业设置,到网络应用程序的后台任务,都有队列的存在。
队列也是处理异步请求的理想工具——它能保证请求按接收的顺序来执行,如event队列,promise回调队列
使用队列计算斐波那契数列的第n项
- 斐波那契数列的前两项固定为1
- 后面的项为前两项之和
- 依次向后,这便是斐波那契数列
const fibonacci = (n) => {
const queue = [];
queue.push(1);
queue.push(1);
let index = 0;
while(index < n - 2) {
index += 1;
// 出队列一个元素
const delItem = queue.shift();
// 获取头部值
const headItem = queue[0];
const nextItem = delItem + headItem;
queue.push(nextItem);
}
return queue[queue.length - 1];
}
console.log(fibonacci(9)); // 34