栈
是一种先进后出的数据结构,有进栈和出栈两种操作。
应用:撤销,程序调用的系统栈。
主要有以下这些功能:
- int getSize();//得到栈的长度
- boolean isEmpty(); //判断栈是否为空
- void push(E e);//进栈
- E pop();//出栈
- E peek();//得到栈顶元素
具体实现如下:
栈的接口
public interface Stack<E> {
/**
* 得到栈的长度
* @return
*/
int getSize();
/**
* 判断栈是否为空
*/
boolean isEmpty();
/**
* 进栈
* @param e
*/
void push(E e);
/**
* 出栈
* @return
*/
E pop();
/**
* 得到栈顶元素
* @return
*/
E peek();
}
数组Array引用<数组博客中的源码>
实现数组栈
public class ArrayStack<E> implements Stack<E> {
Array<E> array;
public ArrayStack(int capacity) {
array = new Array<>(capacity);
}
public ArrayStack() {
array = new Array<>();
}
@Override
public int getSize() {
return array.getSize();
}
@Override
public boolean isEmpty() {
return array.isEmpty();
}
@Override
public void push(E e) {
array.addLast(e);
}
@Override
public E pop() {
E e = array.removeLast();
return e;
}
@Override
public E peek() {
return array.getLast();
}
/**
* 得到栈的容积
* @return
*/
public int getCapacity() {
return array.getCapacity();
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Stack:[");
for (int i = 0; i < array.getSize(); i++) {
sb.append(array.get(i));
if(i != array.getSize()-1)
sb.append(",");
}
sb.append("] top");
return sb.toString();
}
}
具体应用:
解决括号匹配问题(来自leetcode)
import java.util.Stack;
class Solution {
/**
* 利用栈解决括号匹配问题
*
* @param s
* @return
*/
public boolean isValid(String s) {
Stack<Character> stack = new Stack<>();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '(' || c == '[' || c == '{') {
stack.push(c);
} else {
if (stack.isEmpty()) {
return false;
}
char topChar = stack.pop();
if (c == ')' && topChar != '(') {
return false;
}
if (c == ']' && topChar != '[') {
return false;
}
if (c == '}' && topChar != '{') {
return false;
}
}
}
return stack.isEmpty();
}
}
队列
是一种先进先出的数据结构。
主要有以下功能:
- void enqueue(E e); //进入队列
- E dequeue(); //出队
- E getFront(); //查看队首元素
- int getSize(); //查看队列元素个数
- Boolean isEmpty(); //判断队列是否为空
具体实现:
队列接口
public interface Queue<E> {
void enqueue(E e); //进入队列
E dequeue(); //出队
E getFront(); //查看队首元素
int getSize(); //查看队列元素个数
Boolean isEmpty(); //判断队列是否为空
}
队列实现+测试
public class ArrayQueue<E> implements Queue<E> {
private Array<E> array;
/**
* 构造函数
*/
public ArrayQueue(int capacity) {
array = new Array<>(capacity);
}
public ArrayQueue() {
array = new Array<>();
}
@Override
public void enqueue(E e) {
array.addLast(e);
}
@Override
public E dequeue() {
return array.removeFirst();
}
@Override
public E getFront() {
// TODO Auto-generated method stub
return null;
}
@Override
public int getSize() {
return array.getSize();
}
@Override
public Boolean isEmpty() {
return array.isEmpty();
}
/**
* 得到队列容量
* @return
*/
public int getCapacity() {
return array.getCapacity();
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Queue:[");
for (int i = 0; i < array.getSize(); i++) {
sb.append(array.get(i));
if(i != array.getSize()-1)
sb.append(",");
}
sb.append("] ");
return sb.toString();
}
public static void main(String[] args) {
ArrayQueue<Integer> array = new ArrayQueue<>();
for (int i = 0; i < 10; i++) {
array.enqueue(i);
System.out.println(array);
}
array.dequeue();
System.out.println(array);
}
}
array使用数组中的源码Array类。
循环队列
public class LoopQueue<E> implements Queue<E> {
private E[] data;
private int size;
private int front, tail; // front为队首,tail为队尾
/**
* 构造函数
*
* @param capacity
*/
public LoopQueue(int capacity) {
// 因为队列判断为空,为满 ,需要浪费一个空间
data = (E[]) new Object[capacity + 1];
size = 0;
front = 0;
tail = 0;
}
/**
* 无参构造函数
*
* @return
*/
public LoopQueue() {
data = (E[]) new Object[10 + 1];
}
public int getcapacity() {
return data.length - 1;
}
@Override
public void enqueue(E e) {
if ((tail + 1) % data.length == front)
resize(getcapacity() * 2);
data[tail] = e;
tail = (tail + 1) % data.length;
size++;
}
@Override
public E dequeue() {
if (isEmpty()) {
throw new IllegalArgumentException("cannot dequeue from an empty queue");
}
E ret = data[front];
front = (front + 1) % data.length;
size--;
if (size == data.length / 4 && getcapacity() / 2 != 0) {
resize(getcapacity() / 2);
}
return ret;
}
@Override
public E getFront() {
if (isEmpty()) {
throw new IllegalArgumentException("cannot dequeue from an empty queue");
}
return data[front];
}
@Override
public int getSize() {
return size;
}
@Override
public Boolean isEmpty() {
return front == tail;
}
/**
* 给队列扩容
*
* @param i
*/
private void resize(int newCapacity) {
E[] newData = (E[]) new Object[newCapacity + 1];
for (int i = 0; i < size; i++) {
newData[i] = data[(i + front) % data.length];
}
data = newData;
front = 0;
tail = size;
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("front: size = "+size + " capacity ="+getcapacity()+"[");
for (int i = front; i != tail; i = (i+1)%data.length) {
sb.append(data[i]);
if((i+1)%data.length != tail)
sb.append(",");
}
sb.append("]tail ");
return sb.toString();
}
public static void main(String[] args) {
LoopQueue<Integer> array = new LoopQueue<>();
for (int i = 0; i < 20; i++) {
array.enqueue(i);
System.out.println(array);
}
array.dequeue();
System.out.println(array);
}
}
最后测试下数组队列和循环队列的性能:
public class Main {
public static double testQueue(Queue<Integer> queue,int opCount) {
long startTime = System.currentTimeMillis();
Random random = new Random();
for (int i = 0; i < opCount; i++) {
queue.enqueue(random.nextInt(Integer.MAX_VALUE));
}
for (int i = 0; i < opCount; i++) {
queue.dequeue();
}
long endTime = System.currentTimeMillis();
return endTime - startTime;
}
public static void main(String[] args) {
int opCount = 100000;
ArrayQueue<Integer> array = new ArrayQueue<>();
System.out.println(testQueue(array,opCount));
LoopQueue<Integer> loop = new LoopQueue<>();
System.out.println(testQueue(loop,opCount));
}
}
发现:数组队列出队时间复杂度是O(n^2),循环队列出队是O(1)。