栈:又名堆栈,它是一种运算受限的线性表。其限制是仅允许在表的一端进行插入和删除运算。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。
栈的基本操作原则是先进后出
队列:队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。
栈的各种操作(Java实现)
public class ArrayStack<E> {
private static final int INITIAL_SIZE = 6;
private E[] elementData;
private int top; // 指向下一个空位置
public ArrayStack(int intialSize) {
E[] data = (E[]) new Object[intialSize];
elementData = data;
top = 0;
}
public ArrayStack() { this(INITIAL_SIZE); }
public E get(int i) {
checkIndex(i);
return elementData[i];
}
public E top() {
return get(top - 1);
}
public boolean isEmpty() {
return top == 0;
}
public int size() {
return top;
}
public void push(E elem) {
ensureSize(top + 1);
elementData[top++] = elem;
}
public E pop() {
int t = top - 1;
E v = get(t);
elementData[t] = null; // happy GC
top = t;
return v;
}
/**
* 弹出n个元素,返回最后被弹出的元素。
* @param n
* @return
*/
public E pop(int n) {
int t = top - n;
E v = get(t);
for (int i = t; i < top; i++) {
elementData[i] = null; // happy GC
}
top = t;
return v;
}
private void ensureSize(int size) {
if (elementData.length < size) {
int newLength = Math.max(elementData.length << 1, size);
E[] newData = (E[]) new Object[newLength];
System.arraycopy(this.elementData, 0, newData, 0, this.elementData.length);
this.elementData = newData;
}
}
private void checkIndex(int i) {
if (i < 0 || i>= top) {
throw new IndexOutOfBoundsException("index " + i + " not in [0, " + (top - 1) + "]");
}
}
}
队列的各种操作(Java实现)
public class IntArrayQueue {
private static final int INITIAL_SIZE = 8;
private static final boolean CHECK_INVARIANT = true;
private int[] elementData;
private int head; // 队列头
private int tail; // 队列尾,指向下一个空位置
private int size;
public IntArrayQueue(int initialSize) {
elementData = new int[initialSize];
}
public IntArrayQueue() {
this(INITIAL_SIZE);
}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
public void enqueue(int i) {
ensureSize(size + 1);
elementData[tail] = i;
tail = incAndRound(tail);
size++;
if (CHECK_INVARIANT) {
checkInvariant();
}
}
private int incAndRound(int i) {
++i;
if (i == elementData.length) {
i = 0;
}
return i;
}
private void ensureSize(int newSize) {
if (elementData.length < newSize) {
int[] oldData = this.elementData;
int[] newData = new int[Math.max(elementData.length << 1, newSize)];
if (size == 0) {
// do nothing
} else if (tail > head) {
System.arraycopy(oldData, head, newData, 0, size);
} else {
System.arraycopy(oldData, head, newData, 0, oldData.length - head);
System.arraycopy(oldData, 0, newData, oldData.length - head, tail);
}
this.elementData = newData;
head = 0;
tail = size;
}
}
public int dequeue() {
if (size == 0) {
throw new IndexOutOfBoundsException("Cannot dequeue empty queue");
}
int result = elementData[head];
head = incAndRound(head);
size--;
if (CHECK_INVARIANT) {
checkInvariant();
}
return result;
}
public int peek() {
if (size == 0) {
throw new IndexOutOfBoundsException("queue is empty");
}
return elementData[head];
}
private void checkInvariant() {
if (size == 0) {
if (head != tail) {
throw new RuntimeException("when size = 0, head(" + head + ") != tail(" + tail + ")");
}
} else {
if (tail > head) {
if (size != (tail - head)) {
throw new RuntimeException("when tail > head, size(" + size + ") != tail(" + tail+") - head(" + head + ")");
}
} else {
if (size != (tail - head + elementData.length)) {
throw new RuntimeException("when tail <= head, size != tail(" + tail + ") - head(" + head + ") + elementData.length(" + elementData.length + ")");
}
}
}
}
}