栈和队列

概念

栈也是用来存储逻辑关系为 "一对一" 数据的线性存储结构。

栈存储结构对数据 "存" 和 "取" 的过程有特殊的要求:

栈只能从表的一端存取数据,另一端是封闭的,如图 1 所示;

 

在栈中,无论是存数据还是取数据,都必须遵循"先进后出"的原则,即最先进栈的元素最后出栈。拿图 1 的栈来说,从图中数据的存储状态可判断出,元素 1 是最先进的栈。因此,当需要从栈中取出元素 1 时,根据"先进后出"的原则,需提前将元素 4、元素 3 、元素 2 从栈中取出,然后才能成功取出元素 1。

 

因此,我们可以给栈下一个定义,即栈是一种只能从表的一端存取数据且遵循 "先进后出" 原则的线性存储结构。

 

通常,栈的开口端被称为栈顶;相应地,封口端被称为栈底。因此,栈顶元素指的就是距离栈顶最近的元素,拿图 2 来说,栈顶元素为元素 4;同理,栈底元素指的是位于栈最底部的元素,图 2 中的栈底元素为元素 1。

 

进栈和出栈

基于栈结构的特点,在实际应用中,通常只会对栈执行以下两种操作:

向栈中添加元素,此过程被称为"进栈"(入栈或压栈);

从栈中提取出指定元素,此过程被称为"出栈"(或弹栈);

 

Stack和Collection的关系

栈的具体实现

栈是一种 "特殊" 的线性存储结构,因此栈的具体实现有以下两种方式:

顺序栈:采用顺序存储结构可以模拟栈存储数据的特点,从而实现栈存储结构;

链栈:采用链式存储结构实现栈结构;

 

两种实现方式的区别,仅限于数据元素在实际物理空间上存放的相对位置,顺序栈底层采用的是数组链栈底层采用的是链表

 

Java中Stack是通过数组实现的,而非链表。

 

Stack的构造函数

Stack只有一个默认构造函数,如下:

Stack()

 

Stack的API

Stack是栈,它常用的API如下:

boolean      empty()

synchronized E                       peek()

synchronized E            pop()

           E             push(E object)

synchronized int           search(Object o)

 

实现解析

Stack实际上也是通过数组去实现的。

执行push时(即,将元素推入栈中),是通过将元素追加的数组的末尾中。

执行peek时(即,取出栈顶元素,不执行删除),是返回数组末尾的元素。

执行pop时(即,取出栈顶元素,并将该元素从栈中删除),是取出数组末尾的元素,然后将该元素从数组中删除。

 

Stack实例

StackTest代码

 

 

队列

概念

队列,也是一种对数据的"存"和"取"有严格要求的线性存储结构。

与栈结构不同的是,队列的两端都"开口",要求数据只能从一端进,从另一端出,如图 1 所示:

 

 

通常,称进数据的一端为 "队尾",出数据的一端为 "队头",数据元素进队列的过程称为 "入队",出队列的过程称为 "出队"。

 

不仅如此,队列中数据的进出要遵循 "先进先出" 的原则,即最先进队列的数据元素,同样要最先出队列。拿图 1 中的队列来说,从数据在队列中的存储状态可以分析出,元素 1 最先进队,其次是元素 2,最后是元素 3。此时如果将元素 3 出队,根据队列 "先进先出" 的特点,元素 1 要先出队列,元素 2 再出队列,最后才轮到元素 3 出队列。

栈和队列不要混淆,栈结构是一端封口,特点是"先进后出";而队列的两端全是开口,特点是"先进先出"。

 

因此,数据从表的一端进,从另一端出,且遵循 "先进先出" 原则的线性存储结构就是队列。

 

Queue和Collection的关系

 

队列的实现

队列存储结构的实现有以下两种方式:

顺序队列:在顺序表的基础上实现的队列结构;

链队列:在链表的基础上实现的队列结构;

 

两者的区别仅是顺序表和链表的区别,即在实际的物理空间中,数据集中存储的队列是顺序队列,分散存储的队列是链队列。

 

Queue 方法

 

添加、删除、查询这些个操作都提供了两种形式,其中一种在操作失败时直接抛出异常,而另一种则返回一个特殊的值:

 

1、add(E),offer(E) 在尾部添加:

boolean add(E e);

boolean offer(E e);

 

共同之处:

禁止添加 null 元素,否则会报空指针 NullPointerException;

 

不同之处:

add() 方法在添加失败(比如队列已满)时会报一些运行时错误,而 offer() 方法即使在添加失败时返回 false。

 

2、remove(), poll() 删除并返回头部:

E remove();

E poll();

 

当队列为空时 remove() 方法会报 NoSuchElementException 错; 而 poll() 不会报错,只会返回 null。

 

3、element(), peek() 获取但不删除:

E element();

E peek();

 

当队列为空时 element() 抛出异常;peek() 不会报错,只会返回 null。

 

posted @ 2020-02-26 16:02  智阿广  阅读(176)  评论(0)    收藏  举报