Stack application--using JavaScript to describe data structures

Source: Internet
Author: User

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.
Stackthe 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.
Stackclass 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 reverseThe 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:

  1. 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).
  2. 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
  3. 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:

  1. Numeric requirements are integers
  2. 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:

    1. The 调度场算法 infix expression is read and the result is calculated rationally.
    2. The critical point operatorStack.readTop() !== ‘undefined‘ is used to determine. Some books use an # end sign, and individuals feel a little cumbersome.
    3. 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.
    4. 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:

  1. Only one disk can be moved at a time;
  2. 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:

    1. Do not delve into every move, abstract understanding
    2. Step one: All non-compliant disks, move from tower A to Tower B cache
    3. Step two: Move the matching disk to Tower C
    4. 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

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.