栈和队列是两种数据存储类型,而之前说到的冒泡排序、选择排序和插入排序是建立在数组上的,而数组是数据存储结构。而栈和队列更多的是作为程序员的工具来使用,它们主要作为构思算法的辅助工具,而不是完全的数据存储工具。并且,还存在受限访问(只允许特定时刻只有一个数据项执行操作)和更加抽象(主要通过接口对它们进行定义,主要实现机制对用户来说是不可见)的特点。
栈:我的看法是,栈类似于容器,增加一个元素时,是在栈顶,而移除一个元素时,也是在栈顶移除。并且,只允许访问一个数据项,即最后插入的数据项。这种机制在不少的编程环境中都很有用,例如利用栈来检验源程序中的小括号、中括号、大括号是否匹配的问题,还有解析算术表达式。它是先进后出。
栈的代码如下:
public class Stack {
private int maxSize;
private long[] stackArray;
private int top;
public Stack(int s) {
// TODO Auto-generated constructor stub
maxSize = s;
stackArray = new long[maxSize];
top = -1;
}
public void push(long j) {
stackArray[++top] = j;
}
public long pop() {
return stackArray[top--];
}
public long peek() {
return stackArray[top];
}
public boolean isEmpty() {
return (top == -1);
}
public boolean isFull() {
return (top == maxSize - 1);
}
}
队列:队列的有点像我们在电影院排队买票的情形。先来到收银台的人,买完票就先进场。后来到的人,必须等前面的人买完票了,才能轮到他买票进场。即先进先出。
队列的两个基本操作:插入和删除。插入是把数据项放入队尾,而删除则是移除队头的数据项。队头和队尾分别指向各自数据项所在的下标位置。但这样可能会遇到一个问题,即当删除几个数据项时,对头也随之指向下标更大的数据项,而当此时需要插入一个新的数据项时,队尾此时已经指向了最后一个数据项的下表,那新插入的元素放在哪里并且队尾如何指向呢?这个时候,就需要循环队列了。需要队尾从下标最大数回绕到下标为0的位置,新的数据项插入到这个位置。
public class Queue {
private int maxSize;
private long[] queArray;
private int front;
private int rear;
private int nItems;
public Queue(int s) {
// TODO Auto-generated constructor stub
maxSize = s;
queArray = new long[maxSize];
front = 0;
rear = -1;
nItems = 0;
}
public void insert(long j){
if(rear == maxSize-1){ //当队尾标志指向当前队列最后一个
rear = -1;
}
queArray[++rear] = j;
nItems++;
}
public long remove(){
long temp = queArray[front++];//因为front初始值为0 则先把下标为0的数赋值给temp 然后自加
if(front == maxSize)
front = 0;
nItems --;
return temp;
}
public long peekFront(){
return queArray[front];
}
public boolean isEmpty(){
return (nItems == 0);
}
public boolean isFull(){
return (nItems == maxSize);
}
public int size(){
return nItems;
}
}
队列的时间复杂度也是O(1)。