什么是栈?
栈是一种线性的数据结构,只能遵循“先入后出”的原则。“先入后出”也就是First In Last Out,简称FILO,也就是最先进入栈的原则需要最后出栈的元素,这个最早进入栈的元素存放位置叫栈底,最后进入的元素存放的位置叫做栈顶。
栈的基本操作
入栈
现有这样一个栈,需要将一个新元素入栈。
将新的元素入栈。
新的元素取代原来的栈顶,成为新的栈顶。
出栈
现在有一个这样的栈,我要让他执行一次出栈操作。
将需要出栈的元素移除,前面的元素就变成了栈顶。
什么是队列?
队列不同于栈的先入后出,队列中的元素只能按照先入先出(First In First Out,FIFO)的方式,队列的出口端叫队头,队列的入口端叫队尾。
为了入队操作方便,把队尾位置规定为最后入队元素的下一个位置,就像这样:
队列的基本操作
入队
现有这样一个队列需要入队。
将需要插入的元素插入队尾。
最后再重新调整队尾指针的位置,需要指向最后一个元素的下一个元素。
出队
根据先入先出的原则,出队需要让队头的元素先出。
出队完成后,队头便成了队头的下一个元素。
循环队列
如果队列不停的入队和出队操作,这个数组固定的空间就会越用越小,像这样:
队列的容量将会越来越小,这时候再插入一个元素。
从上面来看,插入了一个新元素,队尾指针又重新指向了该数组的第一个元素。
现在再插入一个元素:
这时候,新元素又插入了队尾指针的位置,队尾指针又指向了下一个元素,这样一来,整个数组就循环起来了,这就叫做循环队列。
循环队列的判满公式
( 队尾下标 + 1 ) % 数组长度 = 队头下标
当 队尾下标+1 刚好等于 数组长度 时,结果应是0。
例如:队尾下标=15,数组长度=30,队头下标=16。
则:(15 + 1) % 30 = 16
因为,之前说过,队尾的下标是最后一个元素的下一个,实际在队尾的元素其实下标为14,但,队尾指针指向的位置永远空出一位,所以循环队列元素已满。
循环队列的入队
/**
* 入队
* @param element 入队的元素
* @param front 队头下标
* @param rear 队尾下标
*/
public void enQueue(int element) throws Exception{
if((rear+1)%array.length == front) { //判满公式
throw new Exception("队列已满!!");
}
array[rear] = element; //把新值插入队尾下标,也就是队列的下一个元素
rear = (rear+1)%array.length; //重新定义队尾下标(+1就是下标向后移一位)
}
循环队列的出队
/**
* 出队
* @return
*/
public int deQueue() throws Exception{
if(rear == front) {
throw new Exception("队列已空!!");
}
int deQueueElement = array[front]; //队头下标的元素就是要出队的元素
front = (front+1)%array.length; //重新定义队头下标(队头下标向后移一位)
return deQueueElement;
}