Javascript Data Structure and Algorithmic Stack

Keywords: Javascript

A stack is an ordered set that follows the principle of last-in-first-out (ILFO). The newly added or deleted elements are stored in the same section of the stack, called the top of the stack, and the bottom of the stack at the other end. In reality, many examples use this data structure, such as a stack of books and stacked plates. Stacks are usually used to save variables, method calls, and, of course, browser history.

Array-based stack

Create classes

class StackArray {
  constructor() {
    this.items = [];
  }

Adding elements to the top of the stack

push(element) {
    this.items.push(element);
  }

Remove elements from the top of the stack

pop() {
    return this.items.pop();
  }

View stack top elements

peek() {
    return this.items[this.items.length - 1];
  }

Check if the stack is empty


    isEmpty() {
    return this.items.length === 0;
  }

Empty stack elements

clear() {
    this.items = [];
  }

Convert to an array

toArray() {
    return this.items;
  }

Convert to string

toString() {
    return this.items.toString();
  }

stack class based on Javascript object

Create stack class

class Stack {
  constructor() {
    this.count = 0;//Record stack size to help us add and delete operations
    this.items = {};
  }

Adding elements

push(element) {
    this.items[this.count] = element;
    this.count++;
  }

Delete elements

pop() {
    if (this.isEmpty()) {
      return undefined;
    }
    this.count--;
    const result = this.items[this.count];
    delete this.items[this.count];
    return result;
  }

Verify whether a stack is empty and its size

isEmpty() {
    return this.count === 0;
  }

  size() {
    return this.count;
  }

View the value at the top of the stack and empty the stack

peek() {
    if (this.isEmpty()) {
      return undefined;
    }
    return this.items[this.count - 1];
  };
clear() {
    /* while (!this.isEmpty()) {
        this.pop();
      } */
    this.items = {};
    this.count = 0;
  };

Convert to string

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;
  }
}

summary

In addition to the toString method, the time complexity of the other methods we create is O(1), which means that we can directly tap into the target element and manipulate it.

Be careful

So far, we have used ES6 grammar class. Because of the characteristics of JavaScript language, classes can not have private attributes like other languages. That is to say, private attributes can be referenced externally and assigned to them. Look at the following code to see:

const stack = new Stack();
console.log(Object.getOwnPropertyNames(stack));//["count","items"]
console.log(Object.keys(stack));//["count","items"]
console.log(stack.items);//Direct access to private properties

So the problem arises. We just want users to use the attributes or methods we expose. How can we implement private attributes? The author read the summary of his predecessors and wrote it directly.

Protect internal elements of data structures

Underline naming convention

class stack{
    constructor(){
        this._count = 0;
        this._items = {};
    }
};

It's just a convention, depending on the common sense of the developer.

Implementing Symbol Classes with E2015 Limitations

const _items = Symbol('stackItems');
class Stack{
    constructor(){
        this[_items] = [];
    }
};

Although the basic type of Symbol is immutable, the new Object.getOwnPropertySymbols method added in ES2015 still has access to all Symbol attributes in the form of arrays, but we operate on stacks, and this behavior should not occur. Don't worry. There's a third plan.

Implementing Classes with WeakMap of ES2015

const items = new WeakMap();
class Stack{
    constructor(){
        items.set(this,[]);
    },
    push(element){
        const s = items.get(this);
        s.push(element);
    }
}

In this way, we have implemented a completely private property, but the readability of the code is really too bad for the author. I don't know how you feel about it.

Practice of stack

Binary Conversion Algorithms

function baseConverter(decNumber, base) {
  const remStack = new Stack();
  const digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  let number = decNumber;
  let rem;
  let baseString = '';

  if (!(base >= 2 && base <= 36)) {
    return '';
  }

  while (number > 0) {
    rem = Math.floor(number % base);
    remStack.push(rem);
    number = Math.floor(number / base);
  }

  while (!remStack.isEmpty()) {
    baseString += digits[remStack.pop()];
  }

Balanced parentheses algorithm

function parenthesesChecker(symbols) {
  
const stack = new Stack();
  const opens = '([{';
  const closers = ')]}';
  let balanced = true;
  let index = 0;
  let symbol;
  let top;

  while (index < symbols.length && balanced) {
    symbol = symbols[index];
    if (opens.indexOf(symbol) >= 0) {
      stack.push(symbol);
    } else if (stack.isEmpty()) {
      balanced = false;
    } else {
      top = stack.pop();
      if (!(opens.indexOf(top) === closers.indexOf(symbol))) {
        balanced = false;
      }
    }
    index++;
  }
  return balanced && stack.isEmpty();
}

Posted by dormouse1976 on Fri, 16 Aug 2019 02:13:02 -0700