数据结构与算法
队列
是以顺序的方式维护的一组数据集合,在一端添加数据,从另一端移除数据,添加的一端为尾,移除的一端为头。
可分别基于链表、环形数组实现,相关代码,可在我的码云上查看;
案例:
自定义队列接口
// (先进先出)
public interface Queue<E> {
// 向队列添加元素
boolean offer(E e);
// 向队列移除元素
E pool();
// 从队列头获取值,并不移除
E peek();
// 检查队列是否为空,true就是空
boolean isEmpty();
// 检查队列是否满了,true就是满了
boolean isFull();
}
基于环形数组
// 队列 - 基于数组(环形数组)
// 下标计算公式:(开始下标 + 步数) % 数组长度 = 后移后的下标
// 优质算法:下标 & 数组长度
public class Array4Queue<E> implements Queue<E>, Iterable<E> {
private int head = 0;
private int tail = 0;
private E[] arr = null;
// 数组容量-永远是2的幂次方
@SuppressWarnings("all")
public Array4Queue(int num) {
num -= 1;
num |= num >> 1;
num |= num >> 2;
num |= num >> 4;
num |= num >> 8;
num |= num >> 16;
num += 1;
arr = (E[]) new Object[num];
}
// 向队列添加元素
@Override
public boolean offer(E e) {
if (isFull()) {
return false;
}
arr[tail & arr.length - 1] = e;
tail++;
return true;
}
// 向队列移除元素
@Override
public E pool() {
if (isEmpty()) {
return null;
}
E e = arr[head & arr.length - 1];
head++;
return e;
}
// 从队列头获取值,并不移除
@Override
public E peek() {
if (isEmpty()) {
return null;
}
E e = arr[head & arr.length - 1];
return e;
}
// 检查队列是否为空,true就是空
@Override
public boolean isEmpty() {
return tail == head;
}
// 检查队列是否满了,true就是满了
@Override
public boolean isFull() {
return tail - head == arr.length;
}
@Override
public Iterator<E> iterator() {
return new Iterator<E>() {
int n = head;
@Override
public boolean hasNext() {
return n != tail;
}
@Override
public E next() {
E e = arr[n & arr.length - 1];
n++;
return e;
}
};
}
}
基于链表
// 队列 - 基于链表实现
public class LinkListQueue<E> implements Queue<E>, Iterable<E> {
static class Node<E> {
private E value;
private 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 = head;
private int size = 0;
private int num = Integer.MAX_VALUE;
public LinkListQueue() {
}
public LinkListQueue(int num) {
this.num = num;
}
{
head.next = head;
}
// 向队列添加元素
// head null 1 null
// tail 1 null
@Override
public boolean offer(E e) {
if (isFull()) {
return false;
}
Node<E> node = new Node<>(e, head);
tail.next = node;
tail = node;
size++;
return true;
}
// 向队列移除元素
@Override
public E pool() {
if (isEmpty()) {
return null;
}
Node<E> first = head.next;
head.next = first.next;
if (tail == first) {
tail = head;
}
size--;
return first.value;
}
// 从队列头获取值,并不移除
@Override
public E peek() {
if (isEmpty()) {
return null;
}
Node<E> first = head.next;
return first.value;
}
// 检查队列是否为空,true就是空
@Override
public boolean isEmpty() {
return size == 0;
}
// 检查队列是否满了,true就是满了
@Override
public boolean isFull() {
return size >= num;
}
// 遍历
@Override
public Iterator<E> iterator() {
return new Iterator<E>() {
Node<E> n = head.next;
@Override
public boolean hasNext() {
return n != head;
}
@Override
public E next() {
E value = n.value;
n = n.next;
return value;
}
};
}
}
双端队列
两端都可以添加、删除,也可分别基于链表、环形数组实现;
案例:
自定义队列接口
public interface DQueue<E> {
// 向头部添加
boolean offerFirst(E e);
// 向尾部添加
boolean offerLast(E e);
// 从头部移除元素
E poolFirst();
// 从尾部移除元素
E poolLast();
// 从头部获取值,并不移除
E peekFirst();
// 从尾部获取值,并不移除
E peekLast();
// 检查队列是否为空,true就是空
boolean isEmpty();
// 检查队列是否满了,true就是满了
boolean isFull();
}
基于数组
// 双端队列 - 基于-环形数组的队列
public class ArrayDQueue<E> implements DQueue<E>, Iterable<E> {
E[] arr;
private int head;
private int tail;
public ArrayDQueue(int num) {
arr = (E[]) new Object[num + 1];
}
// 加法
private int iec(int i) {
if (i + 1 >= arr.length) {
return 0;
}
return i + 1;
}
// 减法
private int dec(int i) {
if (i - 1 < 0) {
return arr.length - 1;
}
return i - 1;
}
@Override
public boolean offerFirst(E e) {
if (isFull()) {
return false;
}
head = dec(head);
arr[head] = e;
return true;
}
@Override
public boolean offerLast(E e) {
if (isFull()) {
return false;
}
arr[tail] = e;
tail = iec(tail);
return true;
}
@Override
public E poolFirst() {
if (isEmpty()) {
return null;
}
E e = arr[head];
arr[head] = null;
head = iec(head);
return e;
}
@Override
public E poolLast() {
if (isEmpty()) {
return null;
}
tail = dec(tail);
E e = arr[tail];
arr[tail] = null;
return e;
}
@Override
public E peekFirst() {
if (isEmpty()) {
return null;
}
E e = arr[head];
return e;
}
@Override
public E peekLast() {
if (isEmpty()) {
return null;
}
E e = arr[dec(tail)];
return e;
}
@Override
public boolean isEmpty() {
return head == tail;
}
@Override
public boolean isFull() {
if (head > tail) {
return head - tail == 1;
} else if (head < tail) {
return tail - head == arr.length - 1;
} else {
return false;
}
}
@Override
public Iterator<E> iterator() {
return new Iterator<E>() {
int n = head;
@Override
public boolean hasNext() {
return n != tail;
}
@Override
public E next() {
E e = arr[n];
n = iec(n);
return e;
}
};
}
}
优先级队列
它是一端进,另一端出,按优先级进行出队,也是优先级高者先出队列;
自定义队列接口
public interface Priority {
// 返回优先级,数值越大越高
int priority();
}
基于数组(无序数组)
// 优先级队列 - 基于 数组(无序数组) - 数组存入的元素不是按优先级排序的,是无序的
@SuppressWarnings("all")
public class PriorityQueue1<E extends Priority> implements Queue<E> {
Priority[] arr;
int size = 0;
public PriorityQueue1(int num) {
arr = new Priority[num];
}
@Override
public boolean offer(E e) {
if (isFull()) {
return false;
}
arr[size++] = e;
return true;
}
@Override
public E pool() {
if (isEmpty()) {
return null;
}
int i = getMaxIndex();
E e = (E) arr[i];
arr[i] = null;
// 重新排序 , 后面的元素移动到前面
if (i < size - 1) {
System.arraycopy(arr, i + 1, arr, i, size - 1 - i);
}
size--;
return e;
}
// 获取最大下标
private int getMaxIndex() {
int max = 0;
for (int i = 1; i < size; i++) {
if (arr[i].priority() > arr[max].priority()) {
max = i;
}
}
return max;
}
@Override
public E peek() {
if (isEmpty()) {
return null;
}
int i = getMaxIndex();
E e = (E) arr[i];
return e;
}
@Override
public boolean isEmpty() {
return size == 0;
}
@Override
public boolean isFull() {
return size == arr.length;
}
}
延迟队列
根据延时时间确定优先级;
并发非阻塞队列
队列空或者不满时不叫阻塞
// 阻塞队列 - 双锁实现 (添加不影响获取,获取不影响添加)
@SuppressWarnings("all")
public class BlockQueue<E> implements BlockingQueue<E> {
E[] arr;
int head;
int tail;
AtomicInteger size = new AtomicInteger();
public BlockQueue(int num) {
arr = (E[]) new Object[num];
}
Lock headLock = new ReentrantLock();
Lock tailLock = new ReentrantLock();
Condition headCon = headLock.newCondition();
Condition tailCon = tailLock.newCondition();
// 添加,没有返回值,如果队列满了,进行排队等待
public void offer(E e) throws InterruptedException {
int c;
tailLock.lockInterruptibly();
try {
while (isFull()) {
tailCon.await();
}
arr[tail] = e;
if (++tail == arr.length) {
tail = 0;
}
c = size.getAndIncrement();
if (c + 1 < arr.length) {
tailCon.signal();
}
} finally {
tailLock.unlock();
}
if (c == 0) {
headLock.lock();
try {
headCon.signal();
} finally {
headLock.unlock();
}
}
}
// 添加,超时不再等待(毫秒)
public boolean offer(E e, long timeout) throws InterruptedException {
int c;
tailLock.lockInterruptibly();
try {
long t = TimeUnit.MILLISECONDS.toNanos(timeout);
while (isFull()) {
if (t < 0) {
return false; // 等待超时 - 不再等待,返回false,代表添加失败
}
t = tailCon.awaitNanos(t);
}
arr[tail] = e;
if (++tail == arr.length) {
tail = 0;
}
c = size.getAndIncrement();
if (c + 1 < arr.length) {
tailCon.signal();
}
} finally {
tailLock.unlock();
}
if (c == 0) {
headLock.lock();
try {
headCon.signal();
} finally {
headLock.unlock();
}
}
return true;
}
// 移出一个元素,如果队列没有,进行阻塞等待添加
public E pool() throws InterruptedException {
int c;
headLock.lockInterruptibly();
E e;
try {
while (isEmpty()) {
headCon.await();
}
e = arr[head];
arr[head] = null;
if (++head == arr.length) {
head = 0;
}
c = size.getAndDecrement();
if (c > 1) {
headCon.signal();
}
} finally {
headLock.unlock();
}
if (c == arr.length) {
tailLock.lock();
try {
tailCon.signal();
} finally {
tailLock.unlock();
}
}
return e;
}
public boolean isFull() {
return size.get() == arr.length;
}
public String toString() {
return "BlockQueue2{" +
"arr=" + Arrays.toString(arr) +
'}';
}
}
并发阻塞队列
队列空删除阻塞,队列满时添加阻塞
栈
是一种线性的数据结构,只能在一端进行添加数据和移除数据;其中一端是栈顶,另一端不能操作被称作栈低。
可分别基于链表、数组实现,相关代码,可在我的码云上查看;
案例:
自定义栈接口
// (先进后出)
public interface Stack<E> {
// 向栈顶添加元素
boolean push(E e);
// 向栈顶移除元素
E pol();
// 从栈顶获取获取值,并不移除
E peek();
// 检查是否为空,true就是空
boolean isEmpty();
// 检查是否满了,true就是满了
boolean isFull();
}
基于数组实现
public class ArrayStack<E> implements Stack<E>, Iterable<E> {
E[] arr;
int size = 0;
@SuppressWarnings("all")
public ArrayStack(int size) {
arr = (E[]) new Object[size];
}
// 向栈顶添加元素
@Override
public boolean push(E e) {
if (isFull()) {
return false;
}
arr[size] = e;
size++;
return true;
}
// 向栈顶移除元素
@Override
public E pol() {
if (isEmpty()) {
return null;
}
E e = arr[size - 1];
size--;
return e;
}
// 从栈顶获取获取值,并不移除
@Override
public E peek() {
if (isEmpty()) {
return null;
}
E e = arr[size - 1];
return e;
}
// 检查是否为空,true就是空
@Override
public boolean isEmpty() {
return size == 0;
}
// 检查是否满了,true就是满了
@Override
public boolean isFull() {
return size == arr.length;
}
@Override
public Iterator<E> iterator() {
return new Iterator<E>() {
int n = size;
@Override
public boolean hasNext() {
return n > 0;
}
@Override
public E next() {
E e = arr[n - 1];
n--;
return e;
}
};
}
}
基于链表实现
public class LinkListStack<E> implements Stack<E>, Iterable<E> {
static class Node<E> {
private E value;
private 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 size = 0;
private int num = 0;
public LinkListStack(int num) {
this.num = num;
}
// 向栈顶添加元素
@Override
public boolean push(E e) {
if (isFull()) {
return false;
}
Node<E> node = new Node<>(e, head.next);
head.next = node;
size++;
return true;
}
// 向栈顶移除元素
@Override
public E pol() {
if (isEmpty()) {
return null;
}
Node<E> node = head.next;
head.next = node.next;
size--;
return node.value;
}
// 从栈顶获取获取值,并不移除
@Override
public E peek() {
if (isEmpty()) {
return null;
}
Node<E> node = head.next;
return node.value;
}
// 检查是否为空,true就是空
@Override
public boolean isEmpty() {
// return head.next == null;
return size == 0;
}
// 检查是否满了,true就是满了
@Override
public boolean isFull() {
return size == num;
}
@Override
public Iterator<E> iterator() {
return new Iterator<E>() {
Node<E> node = head.next;
@Override
public boolean hasNext() {
return node != null;
}
@Override
public E next() {
E value = node.value;
node = node.next;
return value;
}
};
}
}