数据结构与算法系列六(栈)

1.引子

1.1.为什么要学习数据结构与算法?

有人说,数据结构与算法,计算机网络,与操作系统都一样,脱离日常开发,除了面试这辈子可能都用不到呀!

有人说,我是做业务开发的,只要熟练API,熟练框架,熟练各种中间件,写的代码不也能“飞”起来吗?

于是问题来了:为什么还要学习数据结构与算法呢?

#理由一:
    面试的时候,千万不要被数据结构与算法拖了后腿
#理由二:
    你真的愿意做一辈子CRUD Boy吗
#理由三:
    不想写出开源框架,中间件的工程师,不是好厨子

1.2.如何系统化学习数据结构与算法?

我想好了,还是需要学习数据结构与算法。但是我有两个困惑:

1.如何着手学习呢?

2.有哪些内容要学习呢?

学习方法推荐:

#学习方法
1.从基础开始,系统化学习
2.多动手,每一种数据结构与算法,都自己用代码实现出来
3.思路更重要:理解实现思想,不要背代码
4.与日常开发结合,对应应用场景

学习内容推荐:

数据结构与算法内容比较多,我们本着实用原则,学习经典的、常用的数据结构、与常用算法

#学习内容:
1.数据结构的定义
2.算法的定义
3.复杂度分析
4.常用数据结构
    数组、链表、栈、队列
    散列表、二叉树、堆
    跳表、图
5.常用算法
    递归、排序、二分查找
    搜索、哈希、贪心、分治
    动态规划、字符串匹配

2.考考你

你还记得在数组那一篇中,我们说过基于线性表的数据结构有哪些吗?它们是:数组、链表、栈、队列。

前面我们详细了解了数组和链表,数组和链表是很多数据结构和算法的基础数据结构。比如我们今天要学习的栈,就可以通过数组实现:顺序栈;也可以通过链表实现:链式栈

那么问题来了:栈到底是什么样的数据结构呢?

#考考你:
1.你能用自己的话描述栈吗?
2.你知道栈都有哪些常见的应用场景吗?

3.案例

3.1.栈的定义

栈是一种基于线性表的特殊数据结构,说它特殊,是因为栈是操作受限的。栈只允许在栈顶一端插入数据和删除数据。满足后进先出的特点。

3.2.代码实现

顺序栈代码:

package com.anan.struct.linetable;

/**
 * 顺序栈:基于数组实现
 * @param <E>
 */
public class ArrayStack<E> {

    private Object[] items;
    private int count;// 计数器(统计栈内元素个数)
    private int n;// 栈大小

    public ArrayStack(int capacity){
        this.items = new Object[capacity];
        this.count = 0;
        this.n = capacity;
    }

    /**
     * 入栈操作
     */
    public boolean push(E e ){

        // 检查栈是否满
        if(count == n){
            return false;
        }

        // 将元素放入栈中
        items[count ++] = e;
        return true;
    }

    /**
     * 出栈操作
     */
    public E pop(){
        // 判断栈是否空
        if(count == 0){
            return null;
        }

        // 返回下标为count-1的元素,并且下标-1
        E e = (E)items[count - 1];
        count --;

        return e;
    }

    public int getCount() {
        return count;
    }

    public int getN() {
        return n;
    }
}

测试代码:

package com.anan.struct.linetable;

/**
 * 测试栈
 */
public class ArrayStackTest {

    public static void main(String[] args) {
        // 创建栈对象
        ArrayStack<Integer> stack = new ArrayStack<Integer>(10);

        // 入栈操作
        System.out.println("1.入栈操作-----------------------------");
        for (int i = 0; i < 5; i++) {
            stack.push(i);
            System.out.println("当前入栈元素:" + i);
        }
        System.out.println("出栈前栈中元素个数:" + stack.getCount());

        System.out.println("2.出栈操作-----------------------------");
        // 出栈操作
        for (int i = 0; i < 5; i++) {
            System.out.println("当前出栈元素:" + stack.pop());
        }

        System.out.println("出栈后栈中元素个数:" + stack.getCount());
    }
}

测试结果:

D:2teach1softjdk8injava com.anan.struct.linetable.ArrayStackTest
1.入栈操作-----------------------------
当前入栈元素:0
当前入栈元素:1
当前入栈元素:2
当前入栈元素:3
当前入栈元素:4
出栈前栈中元素个数:5
2.出栈操作-----------------------------
当前出栈元素:4
当前出栈元素:3
当前出栈元素:2
当前出栈元素:1
当前出栈元素:0
出栈后栈中元素个数:0

Process finished with exit code 0

4.讨论分享

#考考你答案:
1.你能用自己的话描述栈吗?
  1.1.栈是基于线性表的数据结构
  1.2.栈一种操作受限的数据结构
  1.3.栈满足后进先出的特点
  1.4.栈只允许在栈顶插入元素、和删除元素
  
2.你知道栈都有哪些常见的应用场景吗?
  2.1.方法调用
    a.在jvm内存结构中,有线程共享的:方法区、堆
    b.在jvm内存结构中,有线程私有的:程序计数器、本地方法栈、虚拟机栈
    c.在虚拟机栈中,每个方法调用都被封装成:栈帧
    d.栈帧内容包含:局部变量表、操作数栈、方法出口信息等
    e.每个方法的调用过程,就是栈帧在虚拟机栈中入栈和出栈过程
    
  2.2.表达式求值
    a.假设有一个表达式:1+1024*1-1
    b.计算机中,如何求解该表达式的值呢?
    c.注意:当然不是人为口算
    d.我们的目的是让计算机能够理解任意表达式
  2.3.表达式求值过程
    a.用两个栈实现表达式求值
    b.一个用于存储数据:操作数栈
    c.一个用于存储运算符:运算符栈
    
    d.从左至右,读取表达式内容
    e.如果是数据,入栈到操作数栈中
    f.如果是运算符,入栈到运算符栈中
    
    g.比较运算符的优先级
    h.如果遇到高优先级的运算符,则将操作数栈的数据出栈
    i.进行计算,把新的计算结果重新入栈到操作数栈
    j.以此类推...直到处理完成整个表达式

jvm内存结构:

表达式求值过程:1+1024*1-1

原文地址:https://www.cnblogs.com/itall/p/12382409.html