数据结构与算法篇 之队列

什么事队列呢?队列你可以理解为排队买票,先来先买,后来的人只能站末尾,不允许插队,先进者先出,这就是经典的队列。

双向队列

队列只支持两种基本的操作,出队和入队,跟栈一样也是一种操作受限的线性表数据结构。

队列的应用非常广泛,例如有循环队列,阻塞队列,并发队列,他们在很多偏底层的系统,框架,中间件开发中,起着关键性的作用,比如高性能队列Disruptor,Linux环形缓存都使用循环并发队列。

跟栈一样,队列可以使用数组实现或者是链表是实现,用数组实现的叫顺序队列,用链表是的叫链式队列

下面看下数组和链表的代码实现

typedef int datatype ;        /*定义队列中数据元素的数据类型*/

#define maxsize 64        /*定义队列的容量*/

typedef struct { 

datatype data[maxsize] ;     /*用数组作为队列的储存空间*/   

 int      front,rear ;     /*指示队头位置和队尾位置的指针*/ }

sequeue ;  /*顺序队列类型定义*/ sequeue *sq ;         /*定义指向顺序队列的指针*/

bool pop(int &val)

{

if(front == rear) return false;

*val = data[front];
rear++;

return true;

}

bool push(int val)

{

if(rear == maxsize) return false;

data[rear] = val;

return true; 

}

上面顺序队列有个缺陷就是,就是数组删除操作会导致数组中的数据不连续,就要采用数据搬移。也就是每次进行出队操作相当于删除数组下标为0的数据,就要搬移整个队列的数据,出队的时间复杂度就会从原来的O(1)变成O(n)。

那有什么方法优化一下呢?

我们先来看看下面这三张图

第一张是一个大小为7,然后里面有四个人在排队

第二张前面两个人出队了,空出来了两个位置

第三张又有三个小伙子进队了,而且后面没有了位置,那现在一次性搬移过去就行,这样局节省了

由图中可以看出,出队操作的时间复杂度还是O(1),进队O(1),均摊

为了避免搬移大量的数据,那就使用链表来实现循环链式队列

#ifndef QNODE_DATATYPE 
#define QNODE_DATATYPE int
#endif

typedef QNODE_DATATYPE  datatype;

// 定义一个循环队列的管理结构体
typedef struct seqent_queue
{
    datatype *queue;
    int front;
    int tail;

    int size;
}queue;

queue *init_queue(int len)
{
    queue *q = calloc(1, sizeof(queue));
    if(q != NULL)
    {
        q->size = len + 1;

        q->queue = calloc(q->size, sizeof(datatype));
        if(q->queue == NULL)
        {
            printf("分配队列空间失败!\n");
            free(q);
            exit(0);
        }

        q->front = q->tail = 0;
    }

    return q;
}

bool is_full(queue *q)判断是否为满队列
{
    return (q->tail + 1)%q->size == q->front;
}

bool en_queue(datatype data, queue *q)q的tail向下一个移,对size取余,防止越界
{
    if(is_full(q))
        return false;

    q->queue[q->tail] = data;
    q->tail = (q->tail+1) % q->size;

    return true;
}

bool is_empty(queue *q)判断是否为空队,也就是
{
    return q->front == q->tail;
}

bool de_queue(datatype data, queue *q)q的front向下一个移,对size取余,防止越界
{
    if(is_empty(q))
        return false;

    data = q->queue[q->front];
    q->front = (q->front+1) % q->size;

    return true;
}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值