栈
定义:栈又称为堆栈,是一种运算受限的线性表,这是因为它仅允许在线性表的固定一端(表尾)进行插入、删除和读取元素等运算,不允许在其他任何位置进行运算
特点:后进先出
时间复杂度:O(1)
一、栈的基本操作:
在Java程序里面用Stack来描述栈的操作,这个类定义如下:
public class Stack< E > extends Vector< E >
可以发现Stack是Vector的子类,所以他底层是数组实现的,且是线程安全的,但他使用的并不是Vector类之中所提供的方法,而是采用如下的几种方法
1.push(E item);
入栈,向栈顶插入一个元素
**将项目推到此堆栈的顶部。**这与addElement(item)效果完全相同
参数:item–要推送到该堆栈上的项。
返回:项参数。
另见:Vector.addElement
可以发现,其调用的是父类Vector的addElement()方法
2.pop();
出栈,删除栈顶元素并返回
移除此堆栈顶部的对象,并将该对象作为此函数的值返回。
返回:此堆栈顶部的对象(向量对象的最后一项)。
抛出:EmptyStackException–如果此堆栈为空。3.empty();
判断栈是否为空
这个就很显而易见了,调用父类的size方法获取元素个数,如果为0,则为空4.peek();
获取栈顶元素
查看此堆栈顶部的对象,而不将其从堆栈中移除。
返回:此堆栈顶部的对象(向量对象的最后一项)。
抛出:EmptyStackException–如果此堆栈为空。
6.search(Object o)
返回对象在此堆栈上的基于1的位置(即若有多个相同的元素,只取离栈顶最近的)。如果对象o作为该堆栈中的一个项出现,则此方法返回从最接近堆栈顶部的引用堆栈顶部的距离;堆栈上最顶端的项被认为位于距离1处。equals方法用于将o与此堆栈中的项进行比较。
返回:离堆栈顶部最近的相同元素的离栈顶的距离;返回值-1表示对象不在堆栈上。
Stack类也可以直接调用其父类的方法,还有很多,这里就不一一列举了
队列
定义:队列简称队,也是运算受限的线性表,仅允许在表的一段插入,另一端删除。允许插入的一端做队尾,进行删除的一端做队首。
特点:先进先出
时间复杂度:O(1)
一、队列的基本操作
在Java程序里面用Queue来描述队列的操作,这个类定义如下:
public interface Queue extends Collection< E >
显而易见,Queue是一个接口,他并不是一个类,他并没有实现的方法体,所以他的方法取决于右侧的实现类。
Queue qu=new LinkedList<>();
Queue使用时要尽量避免使用Collection的add()和remove()方法,而是要使用offer()来加入元素,使用poll()来获取并移出元素。它们的优点是通过返回值可以判断成功与否,add()和remove()方法在失败的时候会抛出异常。 如果要使用前端而不移出该元素,使用element()或者peek()方法。
1.offer();
如果可以在不违反容量限制的情况下立即将指定元素插入此队列中。如果队列已满直接返回false,队列未满则直接插入并返回true;
可以发现其调用了add方法,但其有一个boolean类型返回值
当使用容量受限队列时,此方法通常比add更可取,因为add只能通过抛出异常来插入元素。
抛出:
ClassCastException–如果指定元素的类阻止将其添加到此队列中
NullPointerException–如果指定的元素为null且此队列不允许null元素
IllegalArgumentException–如果此元素的某些属性阻止将其添加到此queu
2.add();
是对offer()方法的简单封装.
如果可以在不违反容量限制的情况下立即将指定元素插入此队列,则会在成功时返回true,如果当前没有可用空间,则会引发IllegalStateException。
add方法又再次调用了linkLast方法,来进行尾插。
抛出:
IllegalStateException–如果此时由于容量限制而无法添加元素
ClassCastException–如果指定元素的类阻止将其添加到此队列中
NullPointerException–如果指定的元素为null且此队列不允许null元素
IllegalArgumentException–如果此元素的某些属性阻止将其添加到此队列中
3.poll();
检索并删除此队列的头,如果此队列为空,则返回null。
4.remove();
检索并删除此队列的头。此方法与轮询的不同之处在于,如果此队列为空,它将引发异常。
调用了LinkedList的移除首元素的方法。抛出:
NoSuchElementException–如果此队列为空
5.peek();
直接取出队头的元素,并不删除.
6.element();
如果队头元素存在则取出并不删除,与poll()功能相同,但是如果头元素不存在,则会抛出异常
抛出:
NoTouchElementException–如果此队列为空
栈与队列速度快慢
1.栈:只能从顶部取数据,也就是说最先进入栈底的,需要遍历整个栈才能取出来,而且在遍历数据的同时需要为数据开辟临时空间,保持数据在遍历前的一致性。
2.队列:基于地址指针进行遍历,而且可以从头部或者尾部进行遍历,但不能同时遍历,无需开辟空间,因为在遍历的过程中不影响数据结构,所以遍历速度要快。
栈与队列的应用
在算法中最常见的便是dfs(深度优先搜索)与bfs(广度优先搜索)
dfs便可以用栈实现
深度优先搜索(DFS)按符合的条件一直向前搜索,以达到目标。但当探索到某一步时,发现原先选择并未达到要求或者无法到达,就退回一步重新选择,这种走不通就退回再选择其他路径的思想成为回溯(注意,回溯是一种思想),而满足回溯条件的某个状态的点称为“回溯点”。 这种探索+回溯思想,称为回溯法。
如迷宫问题,dfs可以找到到达终点的路(注意:不一定是最短路径),同时也可以知道走过的路径。
而bfs,则可以用队列实现
广度优先搜索(也称宽度优先搜索,缩写BFS)是连通图的一种遍历策略。因为它的思想是从一个顶点V0开始,辐射状地优先遍历其周围较广的区域,故得名。
如迷宫问题,bfs可以找到到达终点的最短路路,同时也可以知道到达每个点的所走步数。