数据结构与算法学习笔记之后进先出的“桶”
栈最为一种的常用的数据结构,用“桶”来形容最合适不过;今天我们就来学习一下
1.“后进先出,先进后出”的数据结构。 2.从操作特性来看,是一种“操作受限”的线性表,只可以在一端插入和删除数据。
1.任何数据结构都是对特定应用场景的抽象,栈是一种操作受限的数据结构,其操作特性用数组和链表均可实现,但却暴露太多的操作接口,使用时容易出错;
2.当某个数据集合只涉及在一端插入和删除数据,且满足后进者先出,先进者后出的操作特性时,我们应该首选栈这种数据结构
栈可以用数组,链表来实现
空间复杂度为O(1)
时间复杂度大多数为O(1),特殊情况自动扩容拷贝原数组时为O(n);
均摊时间复杂度接近于O(1);
// 基于数组实现的顺序栈 public class ArrayStack { private String[] items; // 数组 private int count; // 栈中元素个数 private int n; // 栈的大小 // 初始化数组,申请一个大小为 n 的数组空间 public ArrayStack(int n) { this.items = new String[n]; this.n = n; this.count = 0; } // 入栈操作 public boolean push(String item) { // 数组空间不够了,直接返回 false,入栈失败。 if (count == n) return false; // 将 item 放到下标为 count 的位置,并且 count 加一 items[count] = item; ++count; return true; } // 出栈操作 public String pop() { // 栈为空,则直接返回 null if (count == 0) return null; // 返回下标为 count-1 的数组元素,并且栈中元素个数 count 减一 String tmp = items[count-1]; --count; return tmp; } }
(代码来自于网络,如有侵权请告知我删除)
空间复杂度为O(1)
时间复杂度大多数为O(1)
public class StackOfLinked<Item> implements Iterable<Item> { //定义一个内部类,就可以直接使用类型参数 private class Node{ Item item; Node next; } private Node first; private int N; //构造器 public StackOfLinked(){} //添加 public void push(Item item){ Node oldfirst = first; first = new Node(); first.item = item; first.next = oldfirst; N++; } //删除 public Item pop(){ Item item = first.item; first = first.next; N--; return item; } //是否为空 public boolean isEmpty(){ return N == 0; } //元素数量 public int size(){ return N; } //返回栈中最近添加的元素而不删除它 public Item peek(){ return first.item; } @Override public Iterator<Item> iterator() { return new LinkedIterator(); } //内部类:迭代器 class LinkedIterator implements Iterator{ int i = N; Node t = first; @Override public boolean hasNext() { return i > 0; } @Override public Item next() { Item item = (Item) t.item; t = t.next; i--; return item; } } }
(代码来自于网络,如有侵权请告知我删除)
操作系统给每个线程分配了一块独立的内存空间,这块内存被组织成“栈”这种结构,用来存储函数调用时的临时变量。每进入一个函数,就会将其中的临时变量作为栈帧入栈,当被调用函数执行完成,返回之后,将这个函数对应的栈帧出栈。
利用两个栈,一个用来保存操作数,一个用来保存运算符。我们从左向右遍历表达式,当遇到数字,我们就直接压入操作数栈;当遇到运算符,就与运算符栈的栈顶元素进行比较,若比运算符栈顶元素优先级高,就将当前运算符压入栈,若比运算符栈顶元素的优先级低或者相同,从运算符栈中取出栈顶运算符,从操作数栈顶取出2个操作数,然后进行计算,把计算完的结果压入操作数栈,继续比较。