다시 읽기 "자바 스크립트 데이터 구조와 알고리즘을 학습 - 제 3 판"- 제 4 장 스택

시 감안할 때

金山竹影几千秋,云索高飞水自流;
万里长江飘玉带,一轮银月滚金球。
远自湖北三千里,近到江南十六州;
美景一时观不透,天缘有分画中游。

머리말

이 장을 다시 읽어있다 "자바 스크립트 데이터 구조와 알고리즘을 학습 - 제 3 판"기사 시리즈는 데이터 구조를 공유 할이 장, 주니어 파트너 - 이야기는, 후 동생에 당신을 데려 갈 주시기 바랍니다 세계

스택

스택은 무엇입니까? 스택에 따라입니다 밖으로 처음에서 마지막으로 (LIFO) 원칙의 순서를 설정합니다.

또는 스택의 동일 단부에 저장된 삭제 될 새로운 요소를 추가, 스택의 상단라고 상기 다른 단부가 적층 체의 아래쪽이라고한다.

스택에서 새로운 요소는 스택의 상단에 가까운, 오래된 요소는 스택의 바닥 가까이에 있습니다.

스택 기반의 배열

우리는 운영 규칙을 스택 구조를 스택 기반의 배열을 만들 이해

/**
 * 基于数组array的栈Stack
 * @author huxiaoshuai
 */
class Stack {
  // 初始化
  constructor () {
    this.items = []
  }
}

요소의 스택을 저장하는 배열을 사용하여

배열은 우리가 어떤 위치에 요소를 추가하고 제거 할 수 있습니다, 그가에 따라 스택 기반 LIFO의 원리를 우리는 삽입을 캡슐화 및 요소 삭제

방법 기술
푸시 (요소 (들)) 스택의 상단에 하나 (또는 ​​그 이상)의 새로운 요소를 추가
팝() 최상위 요소를 제거, 반환 요소 제거
몰래 엿보다() 스택 요소의 상단을 반환하고, 스택을 변경하지 않는다
비었다() 스택이 비어 있는지, 그것은, 그렇지 않은 경우는 false 비어있는 경우에 true를 돌려줍니다 결정
명확한() 스택의 모든 요소를 ​​제거
크기() 스택의 요소의 수를 돌려줍니다

코드 구현

class Stack {
  // 初始化
  constructor () {
    this.items = []
  }

  /**
   * push() 添加元素到栈顶
   */ 
  push (element) {
    this.items.push(element)
  }

  /**
   * pop() 移除栈顶元素并返回
   */
  pop () {
    return this.items.pop()
  }

  /**
   * peek() 返回栈顶部元素
   */
  peek () {
    return this.items[this.items.length - 1]
  }

  /***
   * isEmpty() 检测栈是否为空
   */
  isEmpty () {
    return this.items.length === 0
  }

  /**
   * size() 返回栈的长度
   */
  size () {
    return this.items.length
  }
  
  /**
   * clear() 清空栈元素
   */
  clear () {
    this.items = []
  }
}

사용 Stack 클래스

const stack = new Stack()

console.log(stack.isEmpty()) // true

// 添加元素
stack.push(5)
stack.push(8)

// 输出元素
console.log(stack.peek()) // 8

stack.push(11)
console.log(stack.size()) // 3
console.log(stack.isEmpty()) // false

stack.push(15)

상기 개략 스택 동작에 근거
상기 개략 스택 동작에 근거

stack.pop()
stack.pop()
console.log(stack.size()) // 2

상기 개략 스택 동작에 근거
상기 개략 스택 동작에 근거

객체 기반의 스택

스택 클래스 쉬운 방법을 만들기 요소를 저장하는 배열을 사용하는 것입니다. 많은 양의 데이터를 처리 할 때, 우리는 또한 데이터가 가장 효율적인 방법을 평가해야합니다.

어레이를 사용하는 경우에있어서의 시간 복잡도의 대부분은 O (N)이다. 간단한 이해하기 : O (n)은 당신이 최악의 경우보고, n은 배열의 길이를 나타내는 배열을 반복 할 필요가 찾을 때까지 우리는 배열 요소 전반에 걸쳐 모든 위치를 반복해야하는 것을 의미한다. 더 이상 배열, 더 길어질 수 있습니다 필요한 시간. 또한, 상기 어레이는, 소자의 규칙적 배열을 위해 더 많은 메모리 공간을 차지하기 위해, 요소의 순서 집합이다.

使用JavaScript对象存储所有的栈元素,以实现可以直接获取元素,同时占用较少的内存空间,同时保证所有的元素按照我们的需要进行排列,遵循后进先出(LIFO)原则。

代码实现

/**
 * 基于对象的Stack类
 * @author huxiaoshai
 */
class Stack {
  // 初始化
  constructor () {
    this.items = {}
    this.count = 0
  }

  /**
   * push() 向栈中添加元素
   */
  push (element) {
    this.items[this.count] = element
    this.count++
  }

  /**
   * isEmpty() 判断是否为空
   */
  isEmpty () {
    return this.count === 0
  }

  /**
   * size() 返回栈的长度
   */
  size () {
    return this.count
  }

  /**
   * pop() 栈顶移除元素并返回
   */
  pop () {
    if (this.isEmpty()) {
      return undefined
    }
    this.count--
    let result = this.items[this.count]
    delete this.items[this.count]
    return result
  }

  /**
   * peek() 返回栈顶元素,如果为空则返回undefined
   */
  peek () {
    if (this.isEmpty()) {
      return undefined
    }
    return this.items[this.count - 1]
  }

  /**
   * clear() 清空栈数据
   */
  clear () {
    this.items = {}
    this.count = 0
  }

  /**
   * toString() 实现类似于数组结构打印栈内容
   */
  toString () {
    if (this.isEmpty()) {
      return ''
    }
    let objStr = `${this.items[0]}`
    for (let i = 1; i < this.count; i++) {
      objStr = `${objStr},${this.items[i]}`
    }
    return objStr
  }
}

保护数据结构内部元素

私有属性

有时候我们需要创建供其他开发者使用的数据结构和对象时,我们希望保存内部元素,只有使用允许的方法才能修改内部结构。很不幸,目前JS是没有办法直接声明私有属性的,目前业内主要使用一下几种方式实现私有属性。

  1. 下划线命名约定

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

    这只是约定,一种规范,并不能实际保护数据

  2. 基于ES6的限定作用域Symbol实现类

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

    假的私有属性,ES6新增的Object.getOwnPropertySymbols方法能够获取类里面声明的所有Symbols属性

  3. 基于ES6的WeakMap实现类

    /**
     * 使用WeekMap实现类的私有属性
     */
    const items = new WeakMap()
    console.log(items) // WeakMap { [items unknown] }
    
    class Stack {
      constructor () {
        items.set(this, [])
      }
    
      push (element) {
        const s = items.get(this)
        s.push(element)
      }
    
      pop () {
        const s = items.get(this)
        const r = s.pop()
        return r
      }
    
      toString () {
        const s = items.get(this)
        return s.toString()
      }
    }
    
    const stack = new Stack()
    stack.push(1)
    stack.push(2)
    stack.push(3)
    
    console.log(stack.toString()) // 1,2,3
    console.log(stack.items) // undefined

    使用该方式,items是Stack类里的私有属性,但是此种方式代码的可读性不强,而且在扩展该类时无法继承私有属性。

  4. ECMAScript类属性提案

    有一个关于JavaScript类中增加私有属性的提案。通过在属性前添加井号(#)作为前缀来声明私有属性。

class Stack {
  #count = 0
  #items = []
}

使用栈来解决问题

栈的实际应用非常广泛。在回溯问题中,它可以存储访问过的任务或路径、撤销的操作(后续会在讨论图和回溯问题时进一步详细讲解)。栈的使用场景有很多,如汉诺塔问题、平衡圆括号、计算机科学问题:十进制转二进制问题

/**
 * decimalToBinary() 实现十进制转二进制的算法
 */ 
function decimalToBinary (decNumber) {
  // 实例化栈数据结构
  const remStack = new Stack()
  let number = decNumber
  let rem;
  let binaryString = ''

  // 依次将获取的二进制数压入栈中
  while (number > 0) {
    rem = Math.floor(number % 2)
    remStack.push(rem)
    number = Math.floor(number / 2)
  }
  // 拼接要输出的二进制字符串
  while (!remStack.isEmpty()) {
    binaryString += remStack.pop().toString()
  }
  return binaryString
}

console.log(decimalToBinary(10)) // 1010
console.log(decimalToBinary(23)) // 10111

后记

以上就是胡哥今天给大家分享的内容,喜欢的小伙伴记得收藏转发、点击右下角按钮在看,推荐给更多小伙伴呦,欢迎多多留言交流...

胡哥有话说,一个有技术,有情怀的胡哥!京东开放平台首席前端攻城狮。与你一起聊聊大前端,分享前端系统架构,框架实现原理,最新最高效的技术实践!

를 눌러 스캔 코드 관련, 더 잘 생기고 더 아름다운 요! 어떤 대중의 관심 후 동생 뭔가 후 형제 요 함께 깊이있는 교류를 계속할 수 말할 수 있습니다!

후 동생 뭔가 말을

추천

출처www.cnblogs.com/justbecoder/p/11375372.html