栈
1、栈的概念和结构
栈: 是一种特殊的线性表,只允许在固定的一端进行插入和删除操作。栈中的数据遵循先进后出(FILO)原则。
注意:
数据的出入都是在栈顶进行操作。
进栈:
出栈:
2、栈的实现
栈的实现一般可以使用数组或者链表来实现,数组用的更多一些,因为数组的尾插代价比较小,相对来说更容易。
用数组来实现一个栈:
尾插: 栈的尾插就是将要插入的数据放到数组的末尾,然后将数组内元素的个数加一。
尾删: 栈的尾删直接将数组内元素的个数进行减一操作然后返回这个数组就可以了。
剩下的几个操作也特别简单,看代码就能看懂,就不多做介绍,直接看代码:
public class MyStack {
private int[] array;
int top;
MyStack() {
this.array = new int[100];
this.top = 0;
}
/**
* 压入一个数据,插入一个数据
* 压栈
*
* @param v
*/
public void push(int v) {
//尾插
this.array[this.top++] = v;
}
/**
* 弹栈,出栈
*
* @return 栈顶元素
*/
public int pop() {
//尾删
return this.array[--this.top];
}
/**
* 查看栈顶元素
*
* @return 栈顶元素
*/
public int peek() {
return this.array[this.top - 1];
}
//栈的大小
public int size() {
return this.top;
}
//栈是否为空
public boolean isEmpty() {
return this.top == 0;
}
}
队列
1、队列的概念和结构
队列: 只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出(FIFO)的特点。
2、队列的实现
队列也可以使用数组或者链表来实现,但是使用链表的结构会更好一些,因为出队列的话,如果使用数组,需要在数组最前面进行操作,效率比较低。
入队列: 入队列就相当于链表的尾插,前面的文章中已经讲过多次。
出队列: 出队列就相当于链表的头删。
直接看代码:
public class MyQueue {
private class Node{
int value;
Node next;
}
Node head;
Node last;
MyQueue(){
this.head=this.last=null;
}
/**
* 入队列,把数据插入到队尾(尾插)
* @param v
*/
public void push(int v){
Node node = new Node();
node.value=v;
node.next=null;
if (this.head==null){
this.head=this.last=node;
}else {
this.last.next=this.head=node;
}
}
/**
* 出队列(头删),返回队首元素
* @return
*/
public int pop(){
int v = this.head.value;
if (this.head==null){
this.last=null;
}
this.head=this.head.next;
return v;
}
/**
* 返回队首元素
* @return
*/
public int front(){
return this.head.value;
}
//队列元素个数
public int size(){
Node cur = this.head;
int len = 0;
while (cur!=null){
len++;
cur=cur.next;
}
return len;
}
//队列是否为空
public boolean isEmpty(){
return this.head==null;
}
}
3、循环队列
队列中还有一种叫循环队列,就像操作系统中的生产者消费者模型就使用了循环队列。环形队列既可以使用数组实现,也可以使用循环链表实现。
1)空的循环队列
2)满的循环队列
为了能使用Q.rear=Q.front来区别到底是队空还是队满,我们规定:如果rear+1=front
,我们就认为是队满。
栈和队列的异同
相同点:
1、栈和队列都是线性表
2、都只允许在端点处进行插入和删除操作
3、都可以通过数组或者链表实现
4、插入删除时间复杂度都是O(1),空间复杂度也一样
不同点:
1、栈的特点是先进后出,队列的特点是先进先出
2、栈只允许在一端进行插入和删除操作,允许插入删除的一端叫做栈顶,另一端叫栈底;队列只允许在一端进行插入,另一端进行删除,允许插入的一端叫做队尾,允许删除的一端叫做队头。
3、遍历速度不同。
- 栈只能从头部取数据,也就最先放入的需要遍历整个栈最后才能取出来,而且在遍历数据的时候还得为数据开辟临时空间,保持数据在遍历前的一致性。
- 队列基于地址指针进行遍历,而且可以从头或尾部开始遍历,但不能同时遍历,无需开辟临时空间,因为在遍历的过程中不影响数据结构,速度要快的多。
4、应用场景不同
- 常见栈的应用场景包括:括号问题的求解、表达式的转换和求值、函数调用和递归实现、深度优先搜索遍历等;
- 常见的队列的应用场景包括:计算机系统中各种资源的管理、消息缓冲器的管理、广度优先搜索遍历等。