JS数据结构和算法
栈
后进先出,新元素都靠近栈顶
栈也被用在编程语言的编译器和内存中保存变量、方法调用等,也被用于浏览器历史记录
数组实现
-
用数组保存栈里的元素
-
对元素的插入和删除功能进行限制,使其遵循LIFO
-
实现以下方法
push pop peek isEmpty clear size
class Stack{
constructor() {
this.items = []
}
push = el => {
this.items.push(el)
}
pop = () => (
this.items.pop()
)
peek = () => (
this.items[this.items.length - 1]
)
isEmpty = () => (
this.items.length === 0
)
size = () => (
this.items.length
)
clear = () => {
this.items = []
}
}
对象实现
class Stack {
constructor() {
this.count = 0;
this.items = {};
}
push= element => {
this.items[this.count] = element;
this.count++;
return element;
}
size = () => this.count
isEmpty = () => this.count === 0
pop = () => {
if(this.isEmpty()) return undefined;
this.count--;
const result = this.items[this.count]
delete this.items[this.count]
return result;
}
peek = () => {
if(this.isEmpty()) return undefined;
return this.items[this.count - 1];
}
clear = () => {
this.items = {};
this.count = 0;
}
toString = () => {
if(this.isEmpty()) return '';
let objString = this.items[0];
for(let i = 1; i < this.count; i ++) {
objString = `${objString}, ${this.items[i]}`;
}
return objString;
}
}
JS私有属性
symbol实现
const items = Symbol('stackItems')
class Stack {
constructor() {
this[items] = []
}
push = el => (
this[items].push(el)
)
}
const stack = new Stack()
stack.push(0)
let objectSymbol = Object.getOwnPropertySymbols(stack)
stack[objectSymbols[0]].push(1)
weakMap实现
const items = new WeakMap()
class Stack {
constructor() {
items.set(this, [])
}
push = el => {
const s = items.get(this)
return s.push(el)
}
pop = () => {
const s = items.get(this)
return s.pop()
}
}
队列
先进先出
class Queue {
constructor() {
this.count = 0
this.lowestCount = 0
this.items = {}
}
enqueue = el => {
this.items[this.count] = el
this.count ++
return el
}
dequeue = () => {
if(!this.items[this.lowestCount])
return
const result = this.items[this.lowestCount]
delete this.items[this.lowestCount]
this.lowestCount++
return result
}
peek = () => {
if(this.isEmpty)
return undefined
return this.items[this.lowestCount]
}
isEmpty = () => this.count === this.lowestCount
size = () => this.count - this.lowestCount
clear = () => {
this.count = 0
this.lowestCount = 0
this.items = {}
}
}
双端队列
一种允许从前端和后端添加和移除元素的特殊队列
class Deque {
constructor() {
this.count = 0;
this.lowestCount = 0;
this.items = {};
}
addFront = element => {
if(this.isEmpty()){
this.addBack(element)
} else (this.lowestCount > 0) {
this.lowestCount--;
this.items[this.lowestCount] = element
} else {
// this.lowestCount === 0
for(let i=count;i>0;i--) {
this.items[i]= this.items[i-1]
}
this.lowestCount = 0;
this.items[0] = element;
this.count++;
}
}
addBack = element => {
this.items[this.count] = element;
this.count++;
return element;
}
removeFront = () => {
if (!this.items[this.lowestCount])
return;
const result = this.items[this.lowestCount];
delete this.items[this.lowestCount];
this.lowestCount++;
return result;
}
removeBack = () => {
}
peekFront = () => {
if (this.isEmpty) return void 0;
return this.items[this.lowestCount];
}
peekBack = () => {
if (this.isEmpty) return void 0;
return this.items[this.count - 1];
}
isEmpty = () => this.count === this.lowestCount
size = () => this.count - this.lowestCount
clear = () => {
this.count = 0;
this.lowestCount = 0;
this.items = {};
}
toString = () => {
if (this.isEmpty())
return '';
let objString = `${this.items[this.lowestCount]}`;
for (let i = this.lowestCount + 1; i < this.count; i++) {
objString = `${objString},${this.items[i]}`;
}
return objString;
}
}
链表
动态数据结构,可以随意添加或移除项,它会按需扩容。有序的元素组合,不同于数组,链表中的元素在内存中不是连续放置的,每个元素由一个存储元素本身的节点和一个指向下一个元素的引用组成
class Node {
constructor(el) {
this.element = el
this.next = undefined
}
}
function defaultEquals(a,b) {
return a === b
}
class LinkedList {
constructor(equalsFn = defaultEquals) {
this.count = 0
this.head = undefined
this.equalsFn = equalsFn
}
push = el => {
const node = new Node(el)
let current
if(this.head == null) {
this.head = node
} else {
current = this.head
while(current.next) {
current = current.next
}
current.next = node
}
this.count ++
}
remove = el => {}
indexOf = el => {}
removeAt = index => {
if(index >= 0 && index < this.count) {
let current = this.head
if (index === 0) {
this.head = current.next
} else {
let previous
for(let i = 0; i < index; i++) {
previous = current
current = current.next
}
previous.next = current.next
}
this.count--
return current.element
} else {
return undefined
}
}
}
树
二叉搜索树
只允许在左侧节点存储比父节点小的值,在右侧节点存储比父节点大的值
class Node{
constructor(key) {
this.key = key
this.left = null
this.right = null
}
}
class BST {
constructor() {
this.root = null
}
insert (key) {
if(this.root === null) {
this.root = new Node(key)
} else {
this.insertNode(this.root, key)
}
}
insertNode(node, key) {
if(node.key > key) {
if(node.left == null) {
node.left = new Node(key)
} else {
this.insertNode(node.left, key)
}
} else {
if(node.right == null) {
node.right = new Node(key)
} else {
this.insertNode(node.right, key)
}
}
}
inOrder(cb) {
this.inOrderNode(this.root, cb)
}
inOrderNode(node, cb) {
if(node !== null) {
this.inOrderNode(node.left, cb)
cb(node.key)
this.inOrderNode(node.right, cb)
}
}
search(key) {
return this.searchNode(this.root, key)
}
min() {
return this.minNode(this.root)
}
minNode(node) {
if (node.left == null) {
return node.key
} else {
this.minNode(node.left)
}
}
searchNode(node, key) {
if(node === null) {
return false
}
if (node.key > key) {
return this.searchNode(node.left, key)
} else if (node.key < key) {
return this.searchNode(node.right, key)
} else {
return true
}
}
}