JS
Implement stack structure
One, foreword
A stack, also known as a stack, is a linear table with limited operations. A linear table that restricts insertions and deletions to only the end of the table, is a data structure that restricts insertions and deletions to only one end, the end that is allowed is called the top of the stack, the end that is not allowed is called the bottom of the stack. The other end is called the bottom of the stack. Inserting a new element into a stack, also known as a push, push, or push, is to put the new element on top of the top element of the stack, making it a new top element; Removing an element from a stack, also known as making a stack or making a stack, is to remove the top element of the stack so that its adjacent elements become the new top element.
If you want to use JS to implement the stack structure, you need to ensure that the implementation of the stack has the following basic functions:
-
Push new element
-
Pop removes the top element of the stack
-
Peek returns the top element of the stack
-
The clear empty stack
-
Size Size of the stack, that is, the number of elements
-
IsEmpty whether the stack isEmpty
Once you know what you want to implement, you can start implementing the stack
Two, stack implementation
1. Realization of stack basic functions
class Stack {
constructor() {
this.items = []
}
// Add element
push(el) {
this.items.push(el)
}
// Remove the element at the top of the stack and return its value
pop() {
return this.items.pop()
}
// Return the top element of the stack
peek() {
return this.items[this.items.length - 1]}/ / empty stack
clear() {
this.items = []
}
// Stack size
size() {
return this.items.length
}
// Whether the stack is empty
isEmpty() {
return this.items.length === 0}}const stack = new Stack()
stack.push(1)
stack.push(2)
stack.push(3)
console.log(stack)
stack.items.push(4)
console.log(stack)
Copy the code
Although the above code implements the basic functions of the stack, it is obvious that the outside world can actually access the items variable directly and then modify it directly. This is obviously unreasonable. Normally, the outside world can only modify the stack through the methods provided by the stack, but not directly access the stack. The items variable (that is, the stack array) needs to be privatized so that the outside world cannot access it directly.
2. Symbol
Privatize stack arrays?
const Stack = (function () {
const _items = Symbol(a)return class {
constructor() {
this[_items] = []
}
// Add element
push(el) {
this[_items].push(el)
}
// Remove the element at the top of the stack and return its value
pop() {
return this[_items].pop()
}
// Return the top element of the stack
peek() {
return this[_items][this[_items].length - 1]}/ / empty stack
clear() {
this[_items] = []
}
// Stack size
size() {
return this[_items].length
}
// Whether the stack is empty
isEmpty() {
return this[_items].length === 0}}}) ()const stack = new Stack()
stack.push(1)
stack.push(2)
stack.push(3)
console.log(stack)
stack[_items].push(4) // Uncaught ReferenceError: _items is not defined
console.log(stack)
Copy the code
You can see that it is not possible to access the stack array directly through stack[_items]. But that doesn’t mean other methods can’t work:
const key = Object.getOwnPropertySymbols(stack)[0]
stack[key].push(4)
console.log(stack)
Copy the code
The getOwnPropertySymbols method is provided on the Object. This method retrives the key name of the Object’s property named symbol. This method retrives the stack’s symbol value, thus directly accessing the stack.
3. WeakMap
Make the stack array private
const Stack = (function () {
const _items = new WeakMap(a)return class {
constructor() {
_items.set(this[])},// Add element
push(el) {
_items.get(this).push(el)
}
// Remove the element at the top of the stack and return its value
pop() {
return _items.get(this).pop()
}
// Return the top element of the stack
peek() {
return _items.get(this)[_items.get(this).length - 1]}/ / empty stack
clear() {
_items.set(this[])},// Stack size
size() {
return _items.get(this).length
}
// Whether the stack is empty
isEmpty() {
return _items.get(this).length === 0}}}) ()const stack = new Stack()
stack.push(1)
stack.push(2)
stack.push(3)
console.log(stack.size()) / / 3
console.log(stack.isEmpty()) // false
stack.clear()
console.log(stack.size()) / / 0
console.log(stack.isEmpty()) // true
Copy the code
4. The stack implements decimal conversion
In js, provides the Number. The prototype. The toString method to convert decimal to other base, we can also use his stack this kind of data structure, the transition of decimal.
1) Convert decimal to binary
10/2 = 5, remainder 0, 5/2 = 2, remainder 1, 2/2 = 1, remainder 0, 1/2 = 0, remainder 1Copy the code
So the decimal number 10 is converted to binary, so it becomes 1010. You can see that this structure is a stack, and the remainder is pushed one by one, and then the remainder is taken one by one from the top of the stack, and then the combination is done to get the binary, and then the code is used to implement it:
function baseConversionBy2 (num) {
const stack = new Stack()
let res = ' '
while (num > 0) {
stack.push(num % 2)
num = Math.floor(num / 2)}while(! stack.isEmpty()) { res += stack.pop() }return res
}
console.log(baseConversionBy2(10)) / / 1010
Copy the code
2) Convert decimal to octal
32/8 is equal to 4, and the remainder is 0. 4/8 is equal to 0, and the remainder is 4Copy the code
Converting to octal is 40 code as follows:
function baseConversionBy8 (num) {
const stack = new Stack()
let res = ' '
while (num > 0) {
stack.push(num % 8)
num = Math.floor(num / 8)}while(! stack.isEmpty()) { res += stack.pop() }return res
}
console.log(baseConversionBy8(32)) / / 40
Copy the code
3) Convert from decimal to hexadecimal
960/16 = 60, remainder 0 60/16 = 3, remainder 12 3/16 = 0, remainder 3Copy the code
Hexadecimal is different, when the remainder is greater than 9, use letters instead, 10,11,12,13,14,15 correspond to a,b,c,d,e,f respectively, so here converted to hexadecimal 3c0, the code implementation is as follows:
function baseConversionBy16 (num) {
const stack = new Stack()
let res = ' ',
digits = '0123456789abcde'
while (num > 0) {
stack.push(num % 16)
num = Math.floor(num / 16)}while(! stack.isEmpty()) { res += digits[stack.pop()] }return res
}
console.log(baseConversionBy16(960)) // 3c0
Copy the code
4) Convert decimal to other bases
As you can see, the decimal conversion to 2, 8, and hexadecimal is regular, so the above methods can be combined into one method. The code is as follows:
function baseConversionByAuto (num, base) {
const stack = new Stack()
let res = ' ',
digits = '0123456789abcde'
while (num > 0) {
stack.push(num % base)
num = Math.floor(num / base)
}
while(! stack.isEmpty()) { res += digits[stack.pop()] }return res
}
console.log(baseConversionByAuto(10.2)) / / 1010
console.log(baseConversionByAuto(32.8)) / / 40
console.log(baseConversionByAuto(960.16)) // 3c0
Copy the code
5. Stack judgment balance brackets
Balance bracket
"{[()]}" belongs to balance "{bracket ([)]}" does not belong to balance the brackets "{{/}}" does not belong to balance the brackets "{{([]) (#)} ()}" belongs to balance the open bracket = '{[(' close =')]} 'Copy the code
The left half of open is pushed on the stack in the same order as the right half of close
Code implementation:
function check(str) {
const stack = new Stack()
const open = "{[("
const close = "})"
let balanced = true
let index = 0
let symbol
let top
while (index < str.length && balanced) {
symbol = str[index]
if (open.includes(symbol)) {
stack.push(symbol)
} else {
top = stack.pop()
if(open.indexOf(top) ! == close.indexOf(symbol)) { balanced =false
}
}
index ++
}
if (balanced && stack.isEmpty()) {
return true
}
return false
}
console.log(check("{[()]}")) // true
console.log(check("{([]}")) // false
console.log(check("{{/}}")) // false
console.log(check("{{([] [])}} ()")) // true
Copy the code