• JS 算法与数据结构之栈


    列表是一种最自然的数据组织方式,如果数据存储的顺序不重要,且无需对数据进行查找,那么列表是一种再好不过的数据结构,但对于其它一些应用,列表就显得太过简陋,我们需要一种更复杂的数据结构——栈

    一、 什么是栈

    栈是一种后入先出(LIFO,Last-in-first-out) 的数据结构,其数据只能在栈顶添加或删除,因此操作高效快速。

    栈顶:栈内的元素只能通过列表的一端访问,这一端称为栈顶。

    由于栈后入先出的特点,所以任何不在栈顶的元素都无法访问,要得到栈底的元素,需要先拿掉上面的元素。

    二、栈的操作

    1、入栈

    使用 push() 方法,将一个元素压入栈。

    2、出栈

    使用 pop() 方法,将一个元素弹出栈。

    3、预览栈顶元素

    pop() 方法虽然可以访问栈顶元素,但调用后栈顶元素即被删除了,
    而 peek() 方法则只返回栈顶元素,不删除它,用来预览栈顶元素。

    4、记录栈顶元素位置

    我们用变量 top 来记录栈顶元素的位置,标记哪里可以加入新元素;
    当向栈内压入元素时,top 值增大,当从栈内弹出元素时,top 值减小。

    5、清除栈内所有元素

    用 clear() 方法来清除栈内所有元素

    6、记录栈内元素个数

    用变量 length 来记录栈内元素的个数

    7、表示栈内是否含有元素

    用 empty 属性来表示栈内是否含有元素,用 length 也可达到同样的目的

    三、栈的实现

    1、定义 Stack 类

    function Stack() {
      this.dataStore = []
      this.top = 0
      this.push = push
      this.pop = pop
      this.peek = peek
    }
    

    这里用数组 dataStore 保存栈内元素,构造函数将其初始化为一个空数组。
    变量 top 记录栈顶位置,被构造函数初始化为 0,表示栈顶对应数组的起始位置 0。

    2、实现 push 方法

    当向栈中压入一个新元素时,需要将其保存在数组中变量 top 所对应的位置,然后将 top 值加 1,让其指向数组中下一个空位置。

    function push(element) {
      this.dataStore[this.top++] = element
    }
    

    3、实现 pop 方法

    pop 和 push 相反——返回栈顶元素,同时将变量 top 的值减 1。

    function pop() {
      return this.dataStore[--this.top]
    }
    

    关于 i++ 和 ++i
    使用 i++ 时,i 先将自身的值赋值给变量 a,然后再自增 1
    使用 ++i 时,i 先将自身的值自增 1,再将自增后的值赋值给变量 a

    4、实现 peek 方法

    peek 方法返回数组的第 top-1 个位置的元素,即栈顶元素。

    function peek() {
      return this.dataStore[this.top - 1]
    }
    

    如果对一个空栈调用 peek 方法,结果为 undefined(因为栈是空的,栈顶没有任何元素)。

    5、实现 length 方法

    length 方法通过返回变量 top 值的方法返回栈内的元素个数,可用来了解栈内存储了多少个元素。

    function length() {
      return this.top
    }
    

    6、实现 clear 方法

    clear 方法将变量 top 的值设为 0,用来清空一个栈。

    function clear() {
      this.top = 0
    }
    

    7、测试 Stack 类的实现

    var s = new Stack()
    
    s.push('a')
    s.push('b')
    s.push('c')
    
    console.log(s.length()) // 3
    console.log(s.peek())   // "c"
    
    var poped = s.pop()
    
    console.log(poped)      // "c"
    console.log(s.peek())   // "b"
    
    s.push("d")
    
    console.log(s.peek())   // "d"
    
    s.clear()
    
    console.log(s.length()) // 0
    console.log(s.peek())   // undefined
    

    四、栈的实例

    1、回文判断

    回文:指的是一个单词、短语或数字,从前往后写和从后往前写是一样的,比如:“dad”、“racecar”。

    使用栈可以轻松判断一个字符串是否是回文:
    将字符串的每个字符按从左到右的顺序压入栈,栈内就保存了一个反转后的字符串,尾字符在栈顶,而首字符在栈底;
    通过持续弹出栈内的每个元素就可以得到一个新的字符串,这个字符串与原字符串的顺序相反;
    只需比较新字符串和原字符串是否相等即可。

    function isPalindrome(word) {
      var s = new Stack()
      for (var i = 0; i < word.length; ++i) {
        s.push(word[i])
      }
      var rword = ''
      while (s.length() > 0) {
        rword += s.pop()
      }
      if (word == rword) {
        return true
      } else {
        return false
      }
    }
    
    var word1 = 'hello'
    var word2 = 'racecar'
    
    console.log(isPalindrome(word1))  // false
    console.log(isPalindrome(word2))  // true
    

    2、阶乘计算

    递归可以用来实现阶乘运算

    ① 普通函数递归实现阶乘

    function factorial(n) {
      if (n === 0) {
        return 1
      } else {
        return n * factorial(n - 1)
      }
    }
    
    console.log(factorial(5)) // 120
    

    ② 栈模拟递归实现阶乘

    使用栈来模拟递归实现阶乘,先将数字从 5 到 1 压入栈,然后使用一个循环,将数字挨个弹出连乘即可。

    function factorial(n) {
      var s = new Stack()
      while (n > 1) {
        s.push(n--)
      }
      var product = 1
      while (s.length() > 0) {
        product *= s.pop()
      }
      return product
    }
    
    console.log(factorial(5)) // 120
    
  • 相关阅读:
    python 类 专有方法
    当请求进入Nginx后,每个HTTP执行阶段的作用
    jquery 监听不起效果的小问题汇总
    shell 脚本中 while 只执行一次
    LVS (Linux虚拟服务器)模型及算法
    TCP 通信时序及状态变迁
    Golang 谷歌搜索api 实现搜索引擎(前端 bootstrap + jquery)
    Golang 简单 http 代理转发
    Golang 简单静态web服务器
    Golang TCP转发到指定地址
  • 原文地址:https://www.cnblogs.com/Leophen/p/14868475.html
Copyright © 2020-2023  润新知