Stack, aka stacks, is a linear table in which operations are limited. The limitation is that only one end of the table is allowed to insert and delete operations . This end is called the top of the stack, and the opposite end is called the bottom of the stack.
First, implement a stack class stack
Stack-based features can be used to store arrays of linear tables.
Stack
the structure of the initialization class is as follows:
function Stack(){ this.space = [];}Stack.prototype = { constructor: Stack, /* 接口code */};
Next, it is in the prototype, to,,, and 入栈
出栈
the implementation of the 清空栈
读取栈顶
读取整个栈数据
several interfaces.
Stack
class defaults to the array head as the bottom of the stack, the tail to do the top.
1.1 into the stack
push
The stack can use the JS array push
method to press the data at the end of the array.
Stack.prototype = { push: function(value){ return this.space.push(value); }}
1.2 Out of Stack
pop
The stack also uses the JS array pop
method to eject the data at the end of the array.
Stack.prototype = { pop: function(){ return this.space.pop(); }}
1.3 Emptying the Stack
clear
Emptying the stack is relatively straightforward and resets the array of stored data to an empty array.
Stack.prototype = { clear: function(){ this.space = []; }}
1.4 Reading the top of the stack
readTop
Read the top data of the stack and get it by array subscript. One benefit is that when the subscript is outside the array's valid range, the return value is undefined
.
Stack.prototype = { readTop: function(){ return this.space[this.space.length - 1]; }}
1.4 Reading the entire stack
read
Reads the entire stack data and returns the current array directly.
Stack.prototype = { read: function(){ return this.space; }}
1.5 Aggregation
Finally, after aggregating all the features, as shown below, a stack of data structures is done.
function Stack(){ this.space = [];}Stack.prototype = { constructor: Stack, push: function(value){ return this.space.push(value); }, pop: function(){ return this.space.pop(); }, clear: function(){ this.space = []; }, readTop: function(){ return this.space[this.space.length - 1]; }, read: function(){ return this.space; }};
Second, actual combat
Data structures and algorithms are designed for better and more efficient solution to engineering problems.
Here to learn, to provide a few real cases, to realize the charm of the data structure and algorithm:)
2.1 Arrays
reverse
The implementation
In the current case, the stack will be used to implement the inverse function of the array.
function reverse(arr){ var ArrStack = new Stack(); for(var i = arr.length - 1; i >= 0; i--){ ArrStack.push(arr[i]); } return ArrStack.read();}
As shown in the code, it can be divided into the following steps:
- Instantiate a stack for storing data
- The incoming array is traversed in reverse, and is pressed into the stack one by one
- Finally
read
, using the interface, the output data
It seems very simple, don't worry, complicated in the back:)
2.2 Decimal conversion to Binary
The problem of numerical conversion is the small test sledgehammer of the stack.
Before explaining the conversion method, let's look at a small example:
Converts a decimal 13 to a binary
2 | 13 1  ̄ ̄ ̄ 2 | 6 0  ̄ ̄ ̄ 2 | 3 1  ̄ ̄ ̄ ̄ 1 1
As shown above: The binary code of 13 is 1101
.
will be converted manually into a stack of storage, only the results of 2 of the remainder of the stack is pressed to save, and finally invert the output.
function binary(number){ var tmp = number; var ArrStack = new Stack(); if(number === 0){ return 0; } while(tmp){ ArrStack.push(tmp % 2); tmp = parseInt(tmp / 2, 10); } return reverse(ArrStack.read()).join(‘‘);}binary(14); // 输出=> "1110"binary(1024); // 输出=> "10000000000"
2.3 Expression Evaluation
This case, in fact, can be understood as a simplified version of the eval
method.
The case content is the evaluation of the pair 1+7*(4-2)
.
Before entering the subject, it is necessary to understand the following mathematical theories:
- infix notation (or infix notation) is a general method of arithmetic or logical formula representation, in which the operator is in the middle of the operand in infix form (example: 3 + 4).
- The inverse Polish notation (Reverse Polish notation,rpn, or inverse Polish notation) is a mathematical expression introduced by the Polish mathematician Łukasiewicz 1920, in inverse Polish notation, where all operators are placed behind the operands, So it is also called suffix notation . Inverse Polish notation does not require parentheses to identify the precedence of an operator.
"3-4 + 5" of conventional infix notation "3 4-5 +" in inverse polish notation
- The dispatch-field algorithm (shunting Yard algorithm) is a classical algorithm used to convert infix expressions to suffix expressions, introduced by Edsger Dijkstra, which is named for its operation similar to the train marshalling field.
In advance, this is just the simple version of the implementation. So there are two rules:
- Numeric requirements are integers
- Do not allow extra spaces in an expression
The implementation code is as follows:
function Calculate (exp) {var valuestack = new stack ();//value stack var operatorstack = new stack ();//Operation Fu Yi var expar r = Exp.split ("); Cut string expression var first_operator = [' + ', '-']; Add minus operator var second_operator = [' * ', '/']; multiplication operator var special_operator = [' (', ') ']; parentheses var tmp; Temporarily stores the currently processed character Var Tmpoperator; Temporarily stores the current operator//traversal expression for (var i = 0, len = exparr.length; i < Len; i++) {tmp = Exparr[i]; Switch (TMP) {case ' (': Operatorstack.push (TMP); Break Case ') '://encounters a closing parenthesis, first out the data while in parentheses ((Tmpoperator = Operatorstack.pop ())!== ' (' && typeof tmpoperator!== ' undefined ') {Valuestack.push (calculator, Tmpoperator Ack.pop (), Valuestack.pop ())); } break; Case ' + ': Case '-': while (typeof Operatorstack.readtop ()!== ' undefined ' && Special_operator.indexof (Operatorstack.readtop ()) = = = 1 && (second_operator.indexo F (Operatorstack.readtop ())!==-1 | | TMP! = Operatorstack.readtop ())) {//stack top is multiplication or same priority operation, first out stack Valuestack.push (Calculator (o Peratorstack.pop (), Valuestack.pop (), Valuestack.pop ())); } operatorstack.push (TMP); Break Case ' * ': Case '/': while (typeof operatorstack.readtop ()! = ' undefined ' && First_operator.indexof (Operatorstack.readtop ()) = = = 1 && special_operator.indexof (ope Ratorstack.readtop ()) = = = 1 && tmp! = Operatorstack.readtop ()) {//stack top for same priority Level operations, first out stack Valuestack.push (calculator (Operatorstack.pop (), Valuestack.pop (), Valuestack.pop ())); } operatorstack.push (TMP); Break DeFault:valueStack.push (TMP); }}//Process data in stack while (typeof (Tmpoperator = Operatorstack.pop ())!== ' undefined ') {Valuestack.push (Calcula Tor (Tmpoperator, Valuestack.pop (), Valuestack.pop ())); } return Valuestack.pop (); Release the results of the calculation */* @param operator operator @param initiativenum Active value @param passivitynum passive value */functi On calculator (operator, passivitynum, initiativenum) {var result = 0; Initiativenum = typeof Initiativenum = = = ' undefined '? 0:parseint (Initiativenum, 10); Passivitynum = typeof Passivitynum = = = ' undefined '? 0:parseint (Passivitynum, 10); Switch (operator) {case ' + ': result = Initiativenum + passivitynum; Console.log (' ${initiativenum} + ${passivitynum} = ${result} '); Break Case '-': result = Initiativenum-passivitynum; Console.log (' ${initiativenum}-${passivitynum} = ${result} '); Break Case ' * ': result = Initiativenum * passivitynum; Console.log (' ${initiativenum} * ${passivitynum} = ${result} '); Break Case '/': result = Initiativenum/passivitynum; Console.log (' ${initiativenum}/${passivitynum} = ${result} '); Break Default:; } return result; }}
Implementation ideas:
- The
调度场算法
infix expression is read and the result is calculated rationally.
- The critical point
operatorStack.readTop() !== ‘undefined‘
is used to determine. Some books use an #
end sign, and individuals feel a little cumbersome.
- The string expression is
split
split and then traversed to read, pressing into the stack. Have to calculate the results in advance, to carry out the corresponding stack processing.
- The method of calculating partial results is encapsulated as a separate method
calculator
. Because the number before and after the multiplication operator is different in operation, it is not possible to swap positions at random.
2.4 infix expression converted to suffix expression (inverse polish notation)
Inverse Polish notation, is a computer-friendly notation that does not require the use of parentheses.
The following case is a workaround for the previous case, and it is also used to 调度场算法
convert infix expressions to suffix expressions.
function RPN (exp) {var valuestack = new stack ();//value stack var operatorstack = new stack ();//Operation Fu Yi var exparr = ex P.split ("); var first_operator = [' + ', '-']; var second_operator = [' * ', '/']; var special_operator = [' (', ') ']; var tmp; var tmpoperator; for (var i = 0, len = exparr.length; i < Len; i++) {tmp = Exparr[i]; Switch (TMP) {case ' (': Operatorstack.push (TMP); Break Case ') '://encounters a closing parenthesis, first out the data while in parentheses ((Tmpoperator = Operatorstack.pop ())!== ' (' && typeof tmpoperator!== ' undefined ') {Valuestack.push (Translate, tmpoperator Ck.pop (), Valuestack.pop ())); } break; Case ' + ': Case '-': while (typeof Operatorstack.readtop ()!== ' undefined ' && Special_operator.indexof (Operatorstack.readtop ()) = = =-1 && (Second_operator.indexof (Operatorstack.readtop ())!==-1 | | tmp! = operatorstack.readtop ())) {//stack top is multiplication or same priority operation, first out stack Valuestack.push (Translate (Operatorstack.pop (), Valuestack.pop (), Valuestack.pop ())); } operatorstack.push (TMP); Break Case ' * ': Case '/': while (typeof operatorstack.readtop ()! = ' undefined ' && First_operator.indexof (Operatorstack.readtop ()) = = = 1 && special_operator.indexof (ope Ratorstack.readtop ()) = = = 1 && tmp! = Operatorstack.readtop ()) {//stack top for same priority Level operations, first out stack Valuestack.push (Translate (Operatorstack.pop (), Valuestack.pop (), Valuestack.pop ())); } operatorstack.push (TMP); Break Default:valueStack.push (TMP); }} while (typeof (TmpoperatoR = Operatorstack.pop ())!== ' undefined ') {Valuestack.push (Translate (Tmpoperator, Valuestack.pop (), Valuestack.pop ())); } return Valuestack.pop (); Release the results of the calculation */* @param operator operator @param initiativenum Active value @param passivitynum passive value */functi On translate (operator, passivitynum, initiativenum) {var result = '; Switch (operator) {case ' + ': result = ' ${initiativenum} ${passivitynum} + '; Console.log (' ${initiativenum} + ${passivitynum} = ${result} '); Break Case '-': result = ' ${initiativenum} ${passivitynum}-'; Console.log (' ${initiativenum}-${passivitynum} = ${result} '); Break Case ' * ': result = ' ${initiativenum} ${passivitynum} '; Console.log (' ${initiativenum} * ${passivitynum} = ${result} '); Break Case '/': result = ' ${initiativenum} ${pAssivitynum}/'; Console.log (' ${initiativenum}/${passivitynum} = ${result} '); Break Default:; } return result; }}RPN (' 1+7* (4-2) '); Output = "1 7 4 2-* +"
2.5 Connaught Tower
Hanoi (RTHK: Hanoi) is a mathematical problem formed according to a legend:
There are three Poles a,b,c. A rod has N (n>1) perforated discs, the size of the disk from bottom to top in turn smaller. The following rules are required to move all discs to the C-bar:
- Only one disk can be moved at a time;
- The market cannot be stacked on a small plate.
The classic algorithm application of the stack, the first push is 汉诺塔
.
To understand this algorithm, pay attention to the following points:
- Do not delve into every move, abstract understanding
- Step one: All non-compliant disks, move from tower A to Tower B cache
- Step two: Move the matching disk to Tower C
- Step three: Move all B-tower buffers to Tower C
Here is the code implementation:
var ATower = new Stack(); // A塔var BTower = new Stack(); // B塔var CTower = new Stack(); // C塔 (目标塔)var TIER = 4; // 层数for(var i = TIER; i > 0; i--){ ATower.push(i);}function Hanoi(n, from, to, buffer){ if(n > 0){ Hanoi(n - 1, from, buffer, to); // 所有不符合要求的盘(n-1),从A塔统一移到B塔缓存 to.push(from.pop()); // 将符合的盘(n)移动到C塔 Hanoi(n - 1, buffer, to, from); // 把B塔缓存的盘全部移动到C塔 }}Hanoi(ATower.read().length, ATower, CTower, BTower);
The focus of Hanoi, or by recursion to achieve. Put a big problem through recursion and keep splitting up for smaller problems. Then, focus on solving small problems.
Third, summary
Unconsciously, write a little more orz.
Refer to the reference link in the later chapters, or recommend a look. Perhaps with this article, you will have a deeper understanding.
Reference
[1] infix notation
[2] suffix notation
[3] Scheduling field algorithm
[4] Hanoi
Stack application--using JavaScript to describe data structures