数据结构与算法之栈结构

时光毁灭记忆、已成空白 提交于 2019-12-05 04:30:45

认识栈结构

  • 栈也是一种非常常见的数据结构,并且在程序中的应用非常广泛
  • 数组:
    • 我们知道数组是一种线性结构,并且可以在数组的任意位置插入和删除数据
    • 但是,有些时候,我们为了实现一些功能,必须对这种任意性加以限制
    • 栈和队列就是比较常见的受限的线性结构,我们先来学习栈结构
  • 栈结构:只能栈顶进,也只能栈顶出
  • 插入新元素为入栈/压栈 ,删除元素出栈/退栈

程序中什么是使用栈实现的?

  • 函数调用栈:A调用B ,B调用C,C又调用D
  • 那样在执行过程中,会先将A压入栈,A没有执行完,所以不会弹出栈
  • 在A执行过程中,调用了B,会将B压入到栈,这个时候B在栈顶,A在栈底
  • 以此类推
  • 栈底A->B->C->D栈顶,D执行完,弹出栈,C/B/D依此弹出
  • 所以我们有函数调用栈的称呼,就来自于他们内部的实现机制(通过栈来实现)
    • 递归:如果递归无限次一直调用,就会出现栈溢出的情况,不断压入同一个函数,他前面的函数并不能及时的释放

栈结构面试题:

有六个元素6,5,4,3,2,1的顺序进栈,问下列哪一个不是合法的出栈顺序?()
A.543612     B.453216   c.346521   D.234156

//答案:选c
解析:A答案:65进栈,5出栈,4进栈出栈,3进栈出栈,6出栈,21进栈,1出栈,2出栈
     BC答案依此类推
     六个元素不一定是连续进栈,只是进栈的顺序要这个顺序。

栈结构封装以及常见操作(这里以数组的方式模拟)

  • 实现栈结构有两种比较常见的方式:
    • 基于数组实现
    • 基于链表实现
  • 什么是链表?
    • 也是一种数据结构,目前我们还没有学习,并且js中并没有自带链表结构
    • 后续,我们会自己实现链表结构,并且对比数组和链表的区别
    // method:方法,和某一个对象实例有联系
    // function: 函数 
    // 封装栈类
    function Stack() {
      // 栈中的属性
      this.items = [20,10,100]

      // 栈的相关操作
      // 1.将元素压入到栈
      Stack.prototype.push = function(element){  //给栈类添加原型方法
        this.items.push(element)
      }
      // 2.从栈中取出元素(数组的最后一个元素)
      Stack.prototype.pop = function(){  //给栈类添加原型方法
        return  this.items.pop()
      }
      // 3.查看一下栈顶元素(pop取出会将元素删除,而这里peek只查看)
      Stack.prototype.peek = function(){  
        return  this.items[this.items.length-1]
      }
      // 4.判断栈是否为空
      Stack.prototype.isEmpty = function(){
        return this.items.length ==0
      }
      // 5.获取栈中元素的个数
      Stack.prototype.size = function(){
        return this.items.length
      }
      // 6.toString方法
      Stack.prototype.toString = function(){
        //20  10  12 8  7
        let resultString =''
        for(let i=0 ; i<this.items.length ; i++){
          resultString += this.items[i]+''
        }
        return resultString
      } 
    }

    //栈的使用
    var s = new Stack()
    s.push(77)
    console.log(s)
    
    s.pop()
    s.pop()
    console.log(s)
    
    console.log(s.peek())
    console.log(s.isEmpty())
    console.log(s.size())

栈_十进制转二进制

十进制与二进制如何算?
    十进制数:100
计算:100/2  余数0
计算:50/2   余数0
计算:25/2   余数1
计算:12/2   余数0
计算:6/2    余数0
计算:3/2    余数1
计算:1/2    余数1
    所以从下往上结合:二进制数为1100100

封装函数,将一个十进制转换成二进制:
和栈有什么关系?因为:我们的余数相当于不断压栈,但是确实从最后的栈顶开始取数
代码实现:
// 十进制转二进制
    function dec2bin(decNum) {
      //1.定义栈对象  (这里使用我们上面封装好的Stack栈类)
      var stack = new Stack()

      //2.循环操作 (不确定次数的情况下最好用while循环)
      while (decNum > 0) {
        //2.1 获取余数,并且放入栈中
        stack.push(decNum % 2)

        //2.2 获取整除后的结果,作为下一次运行的数字
        decNum = Math.floor(decNum / 2)
      }

      //从栈中取出0和1
      var binaryString = ''
      while (!stack.isEmpty()) {  //判断是否栈空
        binaryString += stack.pop()  
      }
      return binaryString
    }
    console.log(dec2bin(100))
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!