数据结构与算法专题汇总(七)队列的python实现,循环队列判满,阻塞队列和并发队列,线程池

本文深入探讨了队列数据结构,包括数组和链表实现的顺序队列、循环队列的判空判满条件。进一步讲解了阻塞队列的概念,当队列为空或满时的阻塞操作,以及在并发环境中的线程安全问题。最后,讨论了队列在线程池中的应用,分析了不同处理策略,如非阻塞拒绝和阻塞排队,并对比了无界队列和有界队列的优缺点。

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)%n
head。
会浪费一个数组的存储空间,便于判满。


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.阻塞处理:
将请求排队
基于链表实现:实现无限排队的无界队列,可能导致过多的请求排队等待,响应处理时间过长,不适用于对响应时间比较敏感的系统。
基于数组实现:队列大小有限,排队请求超过队列大小时会被拒绝。适合对响应时间较为敏感的系。
需要合理设置队列大小,过大导致等待请求过多,过小无法充分利用系统资源。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值