• 通过数组的学习,我们复习了数组的一些API,这些在JS中是很基础的。我会从这一节开始,将一些函数整理到自己的github库中,以便大家查看及学习。

    本次内容主要包括

    • 栈数据结构
    • 向栈中增加元素
    • 删除栈中的元素
    • 如何使用Stack类
    • 十进制转二进制

    1. 栈数据结构

    栈是一种遵循后进先出(LIFO = last in first out)原则,是一种用来表示元素的集合,主要操作有两种,pushpop

    push 是向栈的顶部(尾部)中增加一个元素
    pop 是移除栈中最顶端(尾部)的元素

    如图所示

    2. 创建一个基于数组的栈

    根据栈遵循的LIFO的原则,我们需要对元素的插入和删除功能做一些限制,我们要为栈声明以下几种方法

    • push(elements):向栈顶添加一个或几个元素到栈顶
    • pop() : 移除栈顶的元素,返回值为移除的元素
    • peek() : 返回栈顶的元素,不对它做任何处理(只是返回这一值)
    • isEmpty(): 判断栈是否为空
    • clear() : 清空栈中的元素
    • size() : 返回栈中元素的个数,类似于数组的length
    class Stack {
        constructor(){
            this.items = [] // 我们可以用数组来保存栈中的数据
        }
        push(elem){
            this.items.push(elem) // 通过上面的图,我们可以使用数组中的push方法将元素推到栈顶
        }
        pop(){
           return this.items.pop()
        }
        peek(){
          return this.items[this.items.length - 1]  
        }
        isEmpty(){
            return this.items.length === 0
        }
        clear(){
            this.items = []
        }
        size(){
            return this.items.length 
        }
    }
    

    接下来我们使用一下我们封装的Stack

    var stack = new Stack()
    console.log(stack.isEmpty()) // true
    stack.push(9)
    stack.push(8)
    console.log(stack.size()) // 2
    console.log(stack) // Stack { items: [ 9, 8 ] }
    stack.push(7)
    stack.push(6)
    console.log(stack) // Stack { items: [ 9, 8, 7, 6] }
    
    console.log(stack.peek()) // 6
    
    console.log(stack.pop()) // 6
    
    console.log(stack) // Stack { items: [ 9, 8, 7 ] }
    
    stack.clear()
    console.log(stack) // Stack { items: [] }
    

    3. 如何使用Stack类

    在我们使用数组中的方法是,大部分的API的时间复杂度是O(n)

    上述的代码中我们只是在栈顶去推入一个元素。我们现在需要改进一下我们的例子,在Stack的构造函数中增加count的属性,这样可以在栈的任何位置插入元素,下面的代码只拿出来修改的部分

    constructor(){
        this.items = [] // 我们可以用数组来保存栈中的数据
        this.count = 0
    }
    push(elem){
       // this.items.push(elem) // 通过上面的图,我们可以使用数组中的push方法将元素推到栈顶
       this.items[this.count] = elem
       this.count ++
    }
    

    我们测试之后

    var stack = new Stack()
    console.log(stack) // Stack { items: [], count: 0 }
    stack.push(9)
    stack.push(8)
    console.log(stack) // Stack { items: [ 9, 8 ], count: 2 }
    

    同样的思路,我们将其他方法也修改一下,升级后的Stack类如下

    class Stack {
        constructor(){
            this.items = [] // 我们可以用数组来保存栈中的数据
            this.count = 0
        }
        push(elem){
            this.items[this.count] = elem
            this.count++
            // this.items.push(elem)
        }
        pop(){
            if (this.isEmpty()) {
                return undefined 
            }
            const item = this.items[this.count-1]
            this.count--
            return item
        //    return this.items.pop()
        }
        peek(){
            if (this.isEmpty()) {
               return undefined 
            }
            return this.items[this.count - 1]  
        }
        isEmpty(){
            return this.count === 0
        }
        clear(){
            this.items = []
            this.count = 0
        }
        size(){
            return this.count
        }
        
    }
    

    接下来,我们在Stack类中增加一个toString()的方法,将数组结构转化为字符串

    toString(){
        if (this.isEmpty()) {
            return ''
        }
        let objString = `${this.items[0]}`
        for (let i = 1; i < this.items.length; i++) {
            objString = `${objString},${this.items[i]}`
        }
        return objString
    }
    
    var stack = new Stack()
    stack.push(9)
    stack.push(8)
    stack.push(7)
    stack.push(6)
    console.log(stack.toString()) // 9,8,7,6
    

    4. 用栈解决问题

    我们在回溯算法问题中,栈可以用来存储访问过的任务或者路径、撤销操作。又或者在前端访问页面时的历史记录就是一个栈,我们这里介绍的是十进制转化为二进制,以及任意进制转换的算法

    进制转换.png

    通过上述的图我们可以看到十进制转化为二进制的过程

    //  进制转换函数
    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)
        }
        console.log(remStack,'remStack',remStack.isEmpty())
        while (!remStack.isEmpty()) {
            binaryString += remStack.pop().toString()
        }
        return binaryString
    }
    
    console.log(decimalToBinary(10)) // 1010
    

    接下来我们可以对这个函数进行改造一下,让它可以实现任意进制转换

    function baseConvert(decNumber,base) {
        const remStack = new Stack()
        const digits = '0123456789ABCDEFGHIGKLMNOPQRSTUVWXYZ'
        let number = decNumber
        let rem ;
        let binaryString = ''
    
        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()) {
            binaryString += digits[remStack.pop()]
        }
        
        return binaryString
    }
    console.log(baseConvert(100345,3)) // 12002122111
    

    下一篇文章是关于队列的,队列则和我们生活中的排队是一样的,遵循先进先出,后进后出的原则。这也是和栈最重要的区别

  • 相关阅读:
    MyEclipse去除网上复制下来的代码带有的行号
    Python人工智能第二篇
    Celery
    SQLAlchemy介绍
    MongoDB
    第三篇 Flask 中的 request
    linux安装
    第二篇 Flask 中的 Render Redirect HttpResponse
    第九篇 Flask 中的蓝图(BluePrint)
    第一篇 Flask
  • 原文地址:https://www.cnblogs.com/bllx/p/15945987.html
Copyright © 2020-2023  润新知