队列


栈、队列、双端队列和列表都是有序的数据集合,其元素的顺序取决于添加顺序或移除顺序。一旦某个元素被添加进来,它与前后元素的相对位置保持不变。这样的数据集合经常被成为 线性数据结构

基本概念

队列是有序集合,添加操作发生在“尾部”,移除操作则发生在“头部”。新元素从尾部进入队列,然后一直向前移动到头部,直到成为下一个被移除的元素。

队列的特性:

  • FIFO(first-in first-out):先进先出,最新添加的元素必须在队列的尾部等待,在队列中时间最长的元素则排在最前面。

队列的实现

用 Python 实现队列

Python 的列表是有序集合,可以利用列表来实现队列:

class Queue:
    def __init__(self):
        self.items = []

    def isEmpty(self):
        return self.items == []

    def enqueue(self, item):
        self.items.insert(0, item)

    def dequeue(self):
        return self.items.pop()

    def size(self):
        return len(self.items)

以上实现的队列的尾部在列表的位置 0 处,这样可以使用 insert 函数向队列的尾部添加新元素。使用 pop 在队列头部移除元素(列表中的最后一个元素)。所以添加操作的时间复杂度是 O(n),移除操作是 O(1)

用 C 实现队列

顺序存储结构的队列称作顺序队列,C 实现顺序队列是有最大存储限制的,这就会带来问题,顺序队列因为多次入队列和出队列操作出现的尚有存储空间但不能进行入队列操作的溢出称为假溢出。相对于假溢出,一个顺序队列定义的最大存储空间都已存满而又要求进行入队列操作所引起的溢出称为真溢出

为了解决假溢出问题,便提出了顺序循环队列,即把顺序队列所使用的存储空间造成一个逻辑上收尾相连的循环队列。

但是顺序循环队列存在队空状态和队满状态相同,所以存在无法判断队空和队满状态。解决此问题有三种方法:

  • 少用一个存储单元
  • 设置一个标志位
  • 设置一个计数器

顺序循环队列的实现:

#define MaxQueueSize 100
typedef int DataType;

typedef struct SeqCQueue
{
    DataType queue[MaxQueueSize];
    int rear;   // 队尾指针
    int front;  // 队头指针
    int count;  // 计数器
}CQueue;

void queueInit(CQueue *q)
{
    q->rear = 0;
    q->front = 0;
    q->count = 0;
}

int isEmpty(CQueue q)
{
    if (0 != q.count)
        return 0;
    else
        return 1;
}

int enqueue(CQueue *q, DataType item)
{
    if (0 < q->count && q->rear == q->front)
    {
        return 1;
    }
    else
    {
        q->queue[q->rear] = item;
        q->rear = (q->rear + 1) % MaxQueueSize;
        q->count++;
        return 0;
    }
}

int dequeue(CQueue *q, DataType *item)
{
    if (0 == q->count)
    {
        return 1;
    }
    else
    {
        *item = q->queue[q->front];
        q->front = (q->front + 1) % MaxQueueSize;
        q->count--;
        return 0;
    }
    
}

int getqueue(CQueue q, DataType *item)
{
    if (0 == q.count)
    {
        return 1;
    }
    else
    {
        *item = q.queue[q.front];
        return 0;
    }
}

链式存储结构的队列称作链式队列:

typedef int DataType;

typedef struct LQNode
{
    DataType data;
    struct LQNode *next;
}Node;

typedef struct LQueue
{
    Node *front;    // 队头指针
    Node *rear;     // 队尾指针
}Queue;

void queueInit(Queue *q)
{
    q->rear = NULL;
    q->front = NULL;
}

int isEmpty(Queue q)
{
    if (q.front == NULL)
        return 1;
    else 
        return 0;
}

int enqueue(Queue *q, DataType item)
{
    Node *p;
    p = (Node *)malloc(sizeof(Node));
    p->data = item;
    p->next = NULL;

    if (NULL != q->rear)
        q->rear->next = p;
    
    q->rear = p;

    if (NULL == q->front)
        q->front = p;
}

int dequeue(Queue *q, DataType *item)
{
    Node *p;
    if (NULL == q->front)
    {
        return 1;
    }
    else
    {
        *item = q->front->data;
        p = q->front;
        q->front = q->front->next;

        if (NULL == q->front)
            q->rear = NULL;
        
        free(p);

        return 0;
    }
    
}

int getqueue(Queue q, DataType *item)
{
     if (NULL == q.front)
    {
        return 1;
    }
    else
    {
        *item = q.front->data;
        return 0;
    }
}

双端队列

双端队列是与队列类似的有序集合,某种意义上可以理解位栈和队列的结合 。它有一前一后两端,元素在其中保持自己的位置。与队列不同的是,双端队列对于哪一端添加和溢出元素没有任何限制,新元素即可以被添加到前端,也可以被添加到后端。同理,已有的元素也能从任意一端移除。

这里用 Python 实现双端队列:

class Deque:
    def __init__(self):
        self.items = []

    # 检查队列是否为空
    def isEmpty(self):
        return self.items == []
	
    # 在双端队列前端添加一个元素
    def addFront(self, item):
        self.items.append(item)
	
    # 在双端队列后端添加一个元素
    def addRear(self, item):
        self.items.insert(0, item)

    # 在双端队列前端删除一个元素
    def removeFront(self):
        return self.items.pop()

    # 在双端队列后端删除一个元素
    def removeRear(self):
        return self.items.pop(0)

    # 返回队列中元素的数目
    def size(self):
        return len(self.items)

优先级队列

优先级队列是带有优先级的队列。在元素进入队列时区分优先级,出队列操作时不是把队头元素出队列,而是把队列中优先级别最高的数据元素出队列。

用顺序存储结构存储的优先级队列称作顺序优先级队列,用链式存储结构存储的优先级队列称作链式优先级队列。

下面展示了一种顺序优先级队列的设计:

#define MaxQueueSize 100
typedef int ElemType;

typedef struct DataType
{
    int priority;   // 优先级
    ElemType elem;  // 元素
}Type;

typedef struct SeqPQueue
{
    Type queue[MaxQueueSize];
    int size;
}Queue;

void queueInit(Queue *q)
{
    q->size = 0;
}

int isEmpty(Queue q)
{
    if (0 >= q.size)
        return 1;
    else
        return 0;
}

int enqueue(Queue *q, Type item)
{
    if (MaxQueueSize <= q->size)
    {
        return 1;
    }
    else 
    {
        q->queue[q->size] = item;
        q->size++;
        return 0;
    }
}

int dequeue(Queue *q, Type *item)
{
    Type min;
    int minIndex, i;

    if (0 >= q->size)
    {
        return 1;
    }
    else
    {
        min = q->queue[0];
        minIndex = 0;
        for (i = 1; i < q->size; i++)
        {
            if (q->queue[i].priority < min.priority)
            {
                min = q->queue[i];
                minIndex = i;
            }
        }

        *item = q->queue[minIndex];
    
        for (i = minIndex + 1; i < q->size; i++)
        {
            q->queue[i-1] = q->queue[i];
        }

        q->size--;

        return 0;
    }
}

int getqueue(Queue *q, Type *item)
{
    Type min;
    int minIndex, i;

    if (0 >=q->size)
    {
        return 1;
    }
    else
    {
        min = q->queue[0];
        minIndex = 0;

        for (i = 0; i < q->size; i++)
        {
             if (q->queue[i].priority < min.priority)
            {
                min = q->queue[i];
                minIndex = i;
            }
        }
        
        *item = q->queue[minIndex];

        return 0;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二流人物

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值