1.队列
先进先出:入队enqueue(),出队dequeue()
同栈一样,是一种操作受限的线性表数据结构
数组实现队列:顺序队列
链表实现队列:链式队列
//python顺序队列
class queue:
def __init__(self):
self.queue = []
def enqueue(self, item):
self.queue.append(item)
def dequeue(self):
return self.queue.pop(0)
def is_empty(self):
return len(self.queue)==0
def size(self):
return len(self.queue)
顺序队列会存在出队时head–而一直往右的情况,此时队列前部分有大量的空余,此时要进行数据搬移。
可以在入队发现tai移动到最右边时进行整体的数据搬移
若用其他如java语言实现,要规定数组的大小,
判断队列满了的条件为tail == n;
判断队列空的条件为head==tail
// java用数组实现的队列
public class ArrayQueue {
// 数组:items,数组大小:n
private String[] items;
private int n = 0;
// head表示队头下标,tail表示队尾下标
private int head = 0;
private int tail = 0;
// 申请一个大小为capacity的数组
public ArrayQueue(int capacity) {
items = new String[capacity];
n = capacity;
}
// 入队
public boolean enqueue(String item) {
// 如果tail == n 表示队列已经满了
if (tail == n) return false;
items[tail] = item;
++tail;
return true;
}
// 出队
public String dequeue() {
// 如果head == tail 表示队列为空
if (head == tail) return null;
// 为了让其他语言的同学看的更加明确,把--操作放到单独一行来写了
String ret = items[head];
++head;
return ret;
}
}
//链式队列
class Node:
def __init__(self,x):
self.val = x
self.next = None
class LinkQueue:
def __init__(self):
self.head = None
self.n = 0
self.tail = None
def enqueue(self,item):
if not self.head:
self.head = item
self.tail = self.head
else:
self.tail.next = item
self.tail = self.tail.next
self.n += 1
def dequeue(self):
if self.n == 0:
return False
ret = self.head.val
self.head = self.head.next
self.n -= 1
return ret
2.循环队列

循环队列的判空条件:headtail
循环队列的判满条件:(tail+1)%nhead。
会浪费一个数组的存储空间,便于判满。
public class CircularQueue {
// 数组:items,数组大小:n
private String[] items;
private int n = 0;
// head表示队头下标,tail表示队尾下标
private int head = 0;
private int tail = 0;
// 申请一个大小为capacity的数组
public CircularQueue(int capacity) {
items = new String[capacity];
n = capacity;
}
// 入队
public boolean enqueue(String item) {
// 队列满了
if ((tail + 1) % n == head) return false;
items[tail] = item;
tail = (tail + 1) % n;
return true;
}
// 出队
public String dequeue() {
// 如果head == tail 表示队列为空
if (head == tail) return null;
String ret = items[head];
head = (head + 1) % n;
return ret;
}
}
3.阻塞队列和并发队列
阻塞队列:
在队列基础上增加阻塞操作。
队列为空时,出队阻塞;
队列满时,入队阻塞。
即生产者-消费者模型
并发队列:
在enqueue()和dequeue()操作上加锁,即多线程安全问题
4.队列应用—线程池
当我们向固定大小的线程池中请求一个线程时,如果线程池中没有空闲资源了,这个时候线程池如何处理这个请求?是拒绝请求还是排队请求?各种处理策略又是怎么实现的呢?
1.非阻塞处理:
直接拒绝任务
2.阻塞处理:
将请求排队
基于链表实现:实现无限排队的无界队列,可能导致过多的请求排队等待,响应处理时间过长,不适用于对响应时间比较敏感的系统。
基于数组实现:队列大小有限,排队请求超过队列大小时会被拒绝。适合对响应时间较为敏感的系。
需要合理设置队列大小,过大导致等待请求过多,过小无法充分利用系统资源。
本文深入探讨了队列数据结构,包括数组和链表实现的顺序队列、循环队列的判空判满条件。进一步讲解了阻塞队列的概念,当队列为空或满时的阻塞操作,以及在并发环境中的线程安全问题。最后,讨论了队列在线程池中的应用,分析了不同处理策略,如非阻塞拒绝和阻塞排队,并对比了无界队列和有界队列的优缺点。

被折叠的 条评论
为什么被折叠?



