Skip to content

Commit 9f793bc

Browse files
committed
栈描述及其应用
1 parent 7611a01 commit 9f793bc

File tree

7 files changed

+173
-35
lines changed

7 files changed

+173
-35
lines changed

main.js

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1 @@
1-
function ListNode(val) {
2-
this.val = val;
3-
this.next = null;
4-
}
51

6-
const a = new ListNode(1)
7-
const b = new ListNode(2)
8-
const c = new ListNode(4)
9-
a.next = b
10-
b.next = c
11-
12-
c.next = a;
13-
14-
console.log( isCircularLinkList(a) )
15-
16-
const d = new ListNode(1)
17-
const e = new ListNode(3)
18-
const f = new ListNode(4)
19-
d.next = e
20-
e.next = f
21-
22-
function bianli(root, vals = []) {
23-
while (root && root !== null) {
24-
vals.push(root.val)
25-
root = root.next
26-
}
27-
return vals
28-
}
29-
// bianli(a)
30-
// bianli(d)
31-
32-
33-
// console.log(bianli(mergeTwoLists3(a, d)))
34-
35-
import './链表/myLinkList.js'
36-
import { isCircularLinkList } from './utils/linkList.js';

栈/Lru.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
var LRUCache = function(capacity) {
2+
this.keys = [] // 存放key的活跃度
3+
this.cache = Object.create(null) // 缓存对象
4+
this.capacity = capacity // 缓存长度
5+
};
6+
7+
LRUCache.prototype.get = function(key) {
8+
if(this.cache[key]) {
9+
// 调整位置
10+
remove(this.keys, key)
11+
this.keys.push(key)
12+
return this.cache[key]
13+
}
14+
return -1
15+
};
16+
17+
LRUCache.prototype.put = function(key, value) {
18+
if(this.cache[key]) {
19+
// 存在即更新
20+
this.cache[key] = value
21+
remove(this.keys, key)
22+
this.keys.push(key)
23+
} else {
24+
// 不存在即加入
25+
this.keys.push(key)
26+
this.cache[key] = value
27+
// 判断缓存是否已超过最大值
28+
if(this.keys.length > this.capacity) {
29+
removeCache(this.cache, this.keys, this.keys[0])
30+
}
31+
}
32+
};
33+
34+
// 移除 key
35+
function remove(arr, key) {
36+
if (arr.length) {
37+
const index = arr.indexOf(key)
38+
if (index > -1) {
39+
return arr.splice(index, 1)
40+
}
41+
}
42+
}
43+
44+
// 移除缓存中 key
45+
function removeCache(cache, keys, key) {
46+
cache[key] = null
47+
remove(keys, key)
48+
}
49+
50+
var cache = new LRUCache( 2 /* 缓存容量 */ );
51+
52+
cache.put(1, 1);
53+
cache.put(2, 2);
54+
cache.get(1); // 返回 1
55+
cache.put(3, 3); // 该操作会使得密钥 2 作废
56+
cache.get(2); // 返回 -1 (未找到)
57+
cache.put(4, 4); // 该操作会使得密钥 1 作废
58+
cache.get(1); // 返回 -1 (未找到)
59+
cache.get(3); // 返回 3
60+
cache.get(4); // 返回 4

栈/images/2021-05-29-13-09-42.png

112 KB
Loading

栈/images/2021-05-29-13-11-13.png

30.9 KB
Loading

栈/stack.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
export const Stack = (function() {
2+
const items = new WeakMap();
3+
class Stack {
4+
constructor() {
5+
items.set(this, []);
6+
}
7+
getItems() {
8+
let s = items.get(this);
9+
return s;
10+
}
11+
push(element) {
12+
this.getItems().push(element);
13+
}
14+
pop() {
15+
return this.getItems().pop();
16+
}
17+
peek() {
18+
return this.getItems()[this.getItems.length - 1];
19+
}
20+
isEmpty() {
21+
return this.getItems().length == 0;
22+
}
23+
size() {
24+
return this.getItems().length;
25+
}
26+
clear() {
27+
this.getItems() = [];
28+
}
29+
}
30+
return Stack;
31+
})();

栈/stack.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# 数据结构之栈
2+
1、栈 是一种遵循 后进先出(LIFO) 原则的有序集合。新添加和待删除的数据都保存在栈的同一端栈顶,另一端就是栈底。新元素靠近栈顶,旧元素靠近栈底。
3+
栈由编译器自动分配释放。栈使用一级缓存。调用时处于存储空间,调用完毕自动释放。
4+
举个栗子:乒乓球盒子/搭建积木
5+
![](images/2021-05-29-13-09-42.png)
6+
7+
2.2 基本数据结构的存储(存储栈)
8+
javaScript中,数据类型分为基本数据类型和引用数据类型,基本数据类型包含:string、number、boolean、undefined、null、symbol、bigint这几种。在内存中这几种数据类型存储在栈空间,我们按值访问。原型类型都存储在栈内存中,是大小固定并且有序的。
9+
![](images/2021-05-29-13-11-13.png)
10+
11+
2.3 执行栈(函数调用栈)
12+
我们知道了基本数据结构的存储之后,我们再来看看JavaScript中如何通过栈来管理多个执行上下文。
13+
14+
程序执行进入一个执行环境时,它的执行上下文就会被创建,并被推入执行栈中(入栈)。
15+
程序执行完成时,它的执行上下文就会被销毁,并从栈顶被推出(出栈),控制权交由下一个执行上下文。
16+
17+
JavaScript中每一个可执行代码,在解释执行前,都会创建一个可执行上下文。按照可执行代码块可分为三种可执行上下文。
18+
19+
全局可执行上下文:每一个程序都有一个全局可执行代码,并且只有一个。任何不在函数内部的代码都在全局执行上下文。
20+
函数可执行上下文:每当一个函数被调用时, 都会为该函数创建一个新的上下文。每个函数都被调用时都会创建它自己的执行上下文。
21+
Eval可执行上下文:Eval也有自己执行上下文。
22+
23+
因为JS执行中最先进入全局环境,所以处于"栈底的永远是全局环境的执行上下文"。而处于"栈顶的是当前正在执行函数的执行上下文",当函数调用完成后,它就会从栈顶被推出(理想的情况下,闭包会阻止该操作,闭包后续文章深入详解)。
24+
"全局环境只有一个,对应的全局执行上下文也只有一个,只有当页面被关闭之后它才会从执行栈中被推出,否则一直存在于栈底"
25+
看个例子:
26+
let name = '蜗牛';
27+
28+
function sayName(name) {
29+
sayNameStart(name);
30+
}
31+
function sayNameStart(name) {
32+
sayNameEnd(name);
33+
}
34+
function sayNameEnd(name) {
35+
console.log(name);
36+
}
37+
复制代码当代码进行时声明:
38+
39+
执行sayName函数时,会把直接函数压如执行栈,并且会创建执行上下文,执行完毕编译器会自动释放:
40+
41+
## 存储栈的应用
42+
43+
### LRU
44+
LRU
45+
在操作系统中, LRU 是一种常用的页面置换算法。其目的在于在发生缺页中断时,将最长时间未使用的页面给置换出去。
46+
要能知道使用最少的键值对 !!!
47+
1.使用秘钥取数据时,就把当前的秘钥移动到数组的最后一项
48+
2.数组的第一项就是使用长时间未使用的缓存数据
49+
50+
### 有效的括号

栈/有效的括号.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// 给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。
2+
3+
// 有效字符串需满足:
4+
5+
// 左括号必须用相同类型的右括号闭合。
6+
// 左括号必须以正确的顺序闭合。
7+
 
8+
var isValid = function (s) {
9+
const n = s.length;
10+
if (n % 2 === 1) {
11+
return false;
12+
}
13+
const map = {
14+
"}": "{",
15+
")": "(",
16+
"]": "[",
17+
}
18+
const tisk = [];
19+
for (let i = 0; i < n; i++) {
20+
const key = s.charAt(i);
21+
if (key == '}' || key == ')' || key == ']') {
22+
if (!tisk.length || tisk[tisk.length - 1] !== map[key]) {
23+
return false
24+
} else {
25+
tisk.pop()
26+
}
27+
} else {
28+
tisk.push(key)
29+
}
30+
}
31+
return !tisk.length
32+
};

0 commit comments

Comments
 (0)