栈(Stack)
栈是一种遵从后进先出(LIFO)原则的有序集合。新添加的或待删除的元素都保存在栈的 同一端,称作栈顶,另一端就叫栈底。在栈里,新元素都靠近栈顶,旧元素都接近栈底。
实现栈结构
const Stack = (() => {
const wm = new WeakMap()
class Stack {
constructor() {
wm.set(this, [])
this.top = 0
}
push(...nums) {
let list = wm.get(this)
nums.forEach(item => {
list[this.top++] = item
})
}
pop() {
let list = wm.get(this)
let last = list[--this.top]
list.length = this.top
return last
}
peek() {
let list = wm.get(this)
return list[this.top - 1]
}
clear() {
let list = wm.get(this)
list.length = 0
}
size() {
return this.top
}
output() {
return wm.get(this)
}
isEmpty() {
return wm.get(this).length === 0
}
}
return Stack
})()
let s = new Stack()
s.push(1, 2, 3, 4, 5)
console.log(s.output()) // [ 1, 2, 3, 4, 5 ]
复制代码
利用栈十进制转化为其他进制
function divideBy2(decNumber, base = 2) {
let remStack = new Stack()
let rem
let binaryString = ''
let digits = '0123456789ABCDEF'
while (decNumber > 0) {
rem = Math.floor(decNumber % base)
remStack.push(rem)
decNumber = Math.floor(decNumber / base)
}
while (!remStack.isEmpty()) {
binaryString += digits[remStack.pop()].toString()
}
return binaryString
}
// 将十进制转换成其他进制
let num = 100345
num.toString(2) // "11000011111111001"
num.toString(8) // "303771"
console.log(divideBy2(num, 2)) // "11000011111111001"
console.log(divideBy2(num, 8)) // "303771"
复制代码
二叉树
二叉搜索树
class Node {
constructor(key) {
this.key = key
this.right = this.left = null
}
}
class BinarySearchTree {
constructor(list = []) {
this.root = null
if (list.length) {
this.root = new Node(list.shift())
list.forEach(item => this.insert(item))
}
}
insert(item) {
let newNode = new Node(item)
if (this.root == null) {
this.root = newNode
} else {
this._insertNode(this.root, newNode)
}
}
_insertNode(node, newNode) {
if (newNode.key < node.key) {
if (node.left === null) {
node.left = newNode
} else {
this._insertNode(node.left, newNode)
}
} else {
if (node.right === null) {
node.right = newNode
} else {
this._insertNode(node.right, newNode)
}
}
}
// 先序遍历 根 左 右
preOrderTraverseNode(node, callback) {
if (node instanceof Node) {
callback(node.key)
this.preOrderTraverseNode(node.left, callback)
this.preOrderTraverseNode(node.right, callback)
}
}
// 中序遍历 左 根 右
inOrderTraverseNode(node, callback) {
if (node instanceof Node) {
this.inOrderTraverseNode(node.left, callback)
callback(node.key)
this.inOrderTraverseNode(node.right, callback)
}
}
// 后序遍历 左 右 根
postOrderTraverseNode(node, callback) {
if (node instanceof Node) {
this.postOrderTraverseNode(node.left, callback)
this.postOrderTraverseNode(node.right, callback)
callback(node.key)
}
}
// 搜索最小值
min() {
return this._minNode(this.root)
}
_minNode(node) {
while (node instanceof Node && node.left) {
node = node.left
}
return node ? node.key : null
}
// 搜索最大值
max() {
return this._maxNode(this.root)
}
_maxNode(node) {
while (node instanceof Node && node.right) {
node = node.right
}
return node ? node.key : null
}
// 搜索特定值
search(key) {
return this._searchNode(this.root, key)
}
_searchNode(node, key) {
if (node instanceof Node) {
if (node.key === key) {
return true
}
if (key < node.key) {
return this._searchNode(node.left, key)
} else {
return this._searchNode(node.right, key)
}
}
return false
}
findMinNode(node) {
while (node && node.left !== null) {
node = node.left
}
return node
}
// 删除指定值
remove(key) {
return this._removeNode(this.root, key)
}
_removeNode(node, key) {
if (node === null) {
return null
}
if (key < node.key) {
// 根据当前node 去它的左子节点继续查找
node.left = this._removeNode(node.left, key)
return node
} else if (key > node.key) {
// 根据当前node 去它的右子节点继续查找
node.right = this._removeNode(node.right, key)
return node
} else {
// 找到了 删除节点
// 情况1:删除节点 没有子节点的情况下 直接删除
if (node.left === null && node.right === null) {
node = null
return node
}
// 情况2:删除节点 只有一个子节点
if (node.left === null) {
node = node.right
return node
} else if (node.right === null) {
node = node.left
return node
}
// 情况3:删除节点 有两个节点
// console.log(node)
// 查找右边最小节点
let min = this.findMinNode(node.right)
node.key = min.key
node.right = this._removeNode(node.right, min.key)
return node
}
}
}
const list = [10, 6, 20, 8, 12, 5, 22]
const tree = new BinarySearchTree(list)
tree.insert(17)
// console.log(tree)
tree.remove(20)
// console.log(tree.min())
// console.log(tree.max())
// 先序遍历
// tree.preOrderTraverseNode(tree.root, key => {
// console.log(key) // 10 6 5 8 20 12 17 22
// })
// 中序遍历
// tree.inOrderTraverseNode(tree.root, key => {
// console.log(key) // 5 6 10 12 17 20 22
// })
// 后序遍历
// tree.postOrderTraverseNode(tree.root, key => {
// console.log(key) // 5 8 6 17 12 22 20 10
// })
复制代码