【数据结构】——队列,栈(基于链表或数组实现)
目录
一.队列
1.基于环形数组实现
两个指针—>需要多一个空位 即定义时,容量+1
2.基于单向环形链表实现(带哨兵)
3.双栈模拟队列
4.双端队列
1.双向链表实现
2.循环数组实现
3.阻塞队列(双锁实现)
二.栈(可以记住来时的路)
1.单向链表实现
2.数组实现
3.力扣20题(有效括号)
一.队列
1.基于环形数组实现
数组实现时,要主要数组下标越界的问题,指针在移动时,用取模的方式移动
两个指针—>需要多一个空位 即定义时,容量+1
public class ArrayQueue4<E> implements Queue<E>, Iterable<E> {static class Node<E>{E value;Node<E> next;public Node(E value, Node<E> next) {this.value = value;this.next = next;}}private E[] array;private int head;private int tail;@SuppressWarnings("all")public ArrayQueue4(int capacity) {this.array = (E[]) new Object[capacity + 1];}@Overridepublic boolean offer(E value) {//判满if (isFull()){return false;}//先赋值再++array[tail] = value;//++要避免越界tail = (tail + 1) % array.length;return true;}@Overridepublic E poll() {//判空if (isEmpty()){return null;}//先赋值再++E e = array[head];//++要避免越界head = (head + 1) % array.length;return e;}@Overridepublic E peek() {//判空if (isEmpty()){return null;}E e = array[head];return e;}@Overridepublic boolean isEmpty() {return head == tail;}@Overridepublic boolean isFull() {return head == (tail + 1) % array.length;}@Overridepublic Iterator<E> iterator() {return new Iterator<E>() {int p = head;@Overridepublic boolean hasNext() {return p != tail;}@Overridepublic E next() {E e = array[p];p = (p + 1) % array.length;return e;}};}
}
2.基于单向环形链表实现(带哨兵)
以head作为哨兵节点。
public class LinkedListQueue1<E> implements Queue<E>, Iterable<E> {private static class Node<E> {E value;Node<E> next;public Node(E value, Node<E> next) {this.value = value;this.next = next;}}private Node<E> head = new Node<>(null, null);private Node<E> tail;private int size;private int capacity = Integer.MAX_VALUE;{this.tail = head;}public LinkedListQueue1(int capacity) {this.capacity = capacity;}public LinkedListQueue1() {}@Overridepublic boolean offer(E value) {if (isFull()){return false;}Node added = new Node<E>(value, head);tail.next = added;tail = added;size++;return true;}@Overridepublic E poll() {if (isEmpty()){return null;}Node removed = head.next;head.next = removed.next;size--;return (E) removed.value;}@Overridepublic E peek() {if (isEmpty()){return null;}Node removed = head.next;return (E) removed.value;}@Overridepublic boolean isEmpty() {return size == 0;}@Overridepublic boolean isFull() {return size == capacity;}@Overridepublic Iterator<E> iterator() {return new Iterator<E>() {Node<E> p = head.next;@Overridepublic boolean hasNext() {return p != head;}@Overridepublic E next() {Node temp = p;p = p.next;return (E) temp.value;}};}
}
3.双栈模拟队列
4.双端队列
1.双向链表实现
不同于单向链表,双向链表只需要一个哨兵阶段即可,不用head,tail节点
public class LinkedListDeque1<E> implements Deque<E>, Iterable<E>{private static class Node<E>{Node<E> prev;E value;Node<E> next;public Node(Node<E> prev, E value, Node<E> next) {this.prev = prev;this.value = value;this.next = next;}}private Node<E> s = new Node<>(null, null, null);private int size;private int capacity;public LinkedListDeque1(int capacity) {this.capacity = capacity;s.next = s;s.prev = s;}public LinkedListDeque1() {}@Overridepublic boolean offerFirst(E e) {if (isFull()){return false;}Node a = s;Node b = s.next;Node<E> addFirst = new Node<>(a, e, b);a.next = addFirst;b.prev = addFirst;size++;return true;}@Overridepublic boolean offerLast(E e) {if (isFull()){return false;}Node a = s.prev;Node b = s;Node<E> addLast = new Node<>(a, e, b);a.next = addLast;s.prev = addLast;size++;return true;}@Overridepublic E pollFirst() {if (isEmpty()){return null;}Node<E> removeFirst = s.next;s.next = removeFirst.next;removeFirst.next.prev = s;size--;return removeFirst.value;}@Overridepublic E pollLast() {if (isEmpty()){return null;}Node<E> removeLast = s.prev;s.prev = removeLast.prev;removeLast.prev.next = s;size--;return removeLast.value;}@Overridepublic E peekFirst() {if (isEmpty()){return null;}Node<E> removeFirst = s.next;return removeFirst.value;}@Overridepublic E peekLast() {if (isEmpty()){return null;}Node<E> removeLast = s.prev;return removeLast.value;}@Overridepublic boolean isEmpty() {return size == 0;}@Overridepublic boolean isFull() {return size == capacity;}@Overridepublic Iterator<E> iterator() {return new Iterator<E>() {Node<E> p = s.next;@Overridepublic boolean hasNext() {return p != s;}@Overridepublic E next() {E e = p.value;p = p.next;return e;}};}
}
2.循环数组实现
public class ArrayDeque3<E> implements Deque<E>, Iterable<E> {E[] array;int head;int tail;@SuppressWarnings("all")public ArrayDeque3(int capacity) {if ((capacity & capacity - 1) != 0) {throw new IllegalArgumentException("capacity 必须是2的幂");}array = (E[]) new Object[capacity];}/*ht0 1 2 3 4 5 6 70 1 2 3 4 5 -1h0 1 2 31 2*/@Overridepublic boolean offerFirst(E e) {if (isFull()) {return false;}array[--head & array.length - 1] = e;return true;}@Overridepublic boolean offerLast(E e) {if (isFull()) {return false;}array[tail++ & array.length - 1] = e;return true;}@Overridepublic E pollFirst() {if (isEmpty()) {return null;}int idx = head++ & array.length - 1;E e = array[idx];array[idx] = null; // help GCreturn e;}@Overridepublic E pollLast() {if (isEmpty()) {return null;}int idx = --tail & array.length - 1;E e = array[idx];array[idx] = null; // help GCreturn e;}@Overridepublic E peekFirst() {if (isEmpty()) {return null;}return array[head & array.length - 1];}@Overridepublic E peekLast() {if (isEmpty()) {return null;}return array[tail-1 & array.length - 1];}@Overridepublic boolean isEmpty() {return tail - head == 0;}/*head=-40 1 2 3a d c b*/@Overridepublic boolean isFull() {return tail - head == array.length - 1;}@Overridepublic Iterator<E> iterator() {return new Iterator<E>() {int p = head;@Overridepublic boolean hasNext() {return p != tail;}@Overridepublic E next() {return array[p++ & array.length - 1];}};}
}
3.阻塞队列(双锁实现)
注意虚假唤醒的问题!
public class BlockingQueue3<E> implements BlockingQueue<E>{//模拟队列private E[] array;private final ReentrantLock headLock = new ReentrantLock();private Condition headWait = headLock.newCondition();private int head;private final ReentrantLock tailLock = new ReentrantLock();private Condition tailWait = tailLock.newCondition();private int tail;private AtomicInteger size = new AtomicInteger(0);public BlockingQueue3(int capacity) {this.array = (E[]) new Object[capacity];}@Overridepublic void offer(E e) throws InterruptedException {int c;tailLock.lockInterruptibly();try {while (isFull()){tailWait.await();}array[tail] = e;tail = (tail + 1) % array.length;c = size.getAndDecrement();} finally {tailLock.unlock();}headLock.lockInterruptibly();try {headWait.signal();} finally {headLock.unlock();}}@Overridepublic boolean offer(E e, long timeout) throws InterruptedException { // 毫秒 5sint c;tailLock.lockInterruptibly();long t = TimeUnit.MILLISECONDS.toNanos(timeout);try {while (isFull()){if (t <= 0){//主要虚假唤醒的问题 线程1唤醒了它 结果另一个线程2又给它放满了return false;}t = tailWait.awaitNanos(t);}array[tail] = e;tail = (tail + 1) % array.length;c = size.getAndDecrement();} finally {tailLock.unlock();}headLock.lockInterruptibly();try {headWait.signal();return true;} finally {headLock.unlock();}}@Overridepublic E poll() throws InterruptedException {int c;E e;headLock.lockInterruptibly();try {while(isEmpty()){headWait.await();}e = array[head];array[head] = null;head = (head + 1) % array.length;c = size.getAndDecrement();} finally {headLock.unlock();}tailLock.lockInterruptibly();try {tailWait.signal();} finally {tailLock.unlock();}return e;}private boolean isEmpty(){return size.get() == 0;}private boolean isFull(){return size.get() == array.length;}@Overridepublic String toString() {return Arrays.toString(array);}
}
二.栈(可以记住来时的路)
1.单向链表实现
static class Node<E> {E value;Node<E> next;public Node(E value, Node<E> next) {this.value = value;this.next = next;}}private Node<E> head = new Node<>(null, null);private int capacity = Integer.MAX_VALUE;private int size = 0;public LinkedListStack(int capacity){this.capacity = capacity;}public LinkedListStack(){}@Overridepublic boolean push(E value) {if (isFull()){return false;}Node<E> next = head.next;Node<E> added = new Node<>(value, next);added.next = next;size++;return true;}@Overridepublic E pop() {if (isEmpty()){return null;}Node<E> removed = head.next;head.next = head.next.next;return removed.value;}@Overridepublic E peek() {if (isEmpty()){return null;}Node<E> removed = head.next;return removed.value;}@Overridepublic boolean isEmpty() {return size == 0;}@Overridepublic boolean isFull() {return size == capacity;}@Overridepublic Iterator<E> iterator() {return new Iterator<E>() {Node<E> p = head;@Overridepublic boolean hasNext() {return p != null;}@Overridepublic E next() {E value = p.value;p = p.next;return value;}};}
2.数组实现
private final E[] array;//栈顶指针private int tail;private int capacity = Integer.MAX_VALUE;@SuppressWarnings("all")public ArrayStack(int capacity){this.array = (E[]) new Object[capacity];}@Overridepublic boolean push(E value) {if (isFull()){return false;}array[tail++] = value;return true;}@Overridepublic E pop() {if (isEmpty()) {return null;}E removed = array[--tail];return removed;}@Overridepublic E peek() {if (isEmpty()) {return null;}E removed = array[tail - 1];return removed;}@Overridepublic boolean isEmpty() {return tail == 0;}@Overridepublic boolean isFull() {return tail == array.length;}@Overridepublic Iterator<E> iterator() {return new Iterator<E>() {int p = tail;@Overridepublic boolean hasNext() {return p > 0;}@Overridepublic E next() {E value = array[--p];return value;}};}
3.力扣20题(有效括号)
思路:
遇到左括号就将其对应的右括号压入栈中,遇到右括号就弹出栈顶元素,看是否与这个有括号匹配。直到弹空
public boolean isValid(String s) {ArrayStack<Character> stack = new ArrayStack<>(s.length());for (int i = 0; i < s.length(); i++){char c = s.charAt(i);if (c == '('){stack.push(')');}else if (c == '['){stack.push(']');}else if (c == '{'){stack.push('}');}else {if (!stack.isEmpty() && c == stack.peek()){stack.pop();}else {return false;}}}return stack.isEmpty();}