数据结构和算法(1) ---- Queue 的原理和实现

Queue 的定义和结构

队列(Queue) 是只允许在一端进行插入,在另一端进行删除的线性表

队列是一种先进先出(First In First Out)的线性表,简称 FIFO(First IN First OUT), 允许插入的一端称为队尾, 允许删除的一端称为队列头

队列的基本结构如下图所示:

Queue 的抽象数据类型

队列也有线性表的各种操作,不同的是插入元素只能在队列尾,删除元素只能在对列头进行:

队列的抽象结构如下所示:

c 复制代码
ADT Queue(队列)
Data:
    同线性表, 元素具有相同的类型,相邻的元素具有前驱和后继关系
Operation:
    InitQueue(Q*)
    DestroyQueue(Q*)
    isEmpty(Q*)
    isFull(Q*)
    dequeue(Q*, *e)
    enqueue(Q*, e)
    queueSize(Q)
endADT

队列有多种实现方式,比如 静态数组,动态数组,单链表,双链表等

静态数组实现Queue

静态数组实现队列的基本原理:

  • 建立一个 MAX_SIZE 的数组, 用于存放 Queue 中的元素
  • 建立int类型 queue->rear 代表队列尾, 每次 enqueue 一个元素时,queu->rear 指向最新的元素位置
  • 建立 queue->front 代表队列头, 每次 dequeue 一个元素,从 queue->front 位置处取出数据,并且最后其指向下一个元素位置
  • queue->rearqueue->front 相等时,queue->frontqueue->rear都重新设置为 0,此时队列为空,表示重新开始存储数据

    参考代码如下:
c 复制代码
#define MAX_SIZE 100
typedef struct {
    int data[MAX_SIZE];
    int front;
    // queue 尾端的索引
    int rear;
}Queue;

void Queueinit(Queue* queue) {
    queue->front = -1;
    queue->rear = -1;
}

int isEmpty(Queue* queue) {
    return (queue->front == -1 && queue->rear == -1);
};

int isFull(Queue* queue) {
    // queue->rear == MAX_SIZE - 1  queue->front = 0
    //return (queue->rear + 1)%MAX_SIZE == queue->front;
    if((queue->rear + 1 - queue->front) == MAX_SIZE) {
        return 1;
    }

    return 0;
};

void enqueue(Queue* queue,int item) {
    if(isFull(queue)) {
        fprintf(stderr,"queue is full. \n");
        return;
    }

    //printf("queue front is %d rear is %d \n",queue->front,queue->rear);
    if(isEmpty(queue)) {
        queue->rear = 0;
        queue->front = 0;
    } else {
        queue->rear = (queue->rear+1)%MAX_SIZE;
    }

    queue->data[queue->rear] = item;
}

int dequeue(Queue* queue) {
    if(isEmpty(queue)) {
        fprintf(stderr,"queue is empty. \n");
        return -1;
    }

    int item = queue->data[queue->front];

    // with no element
    if(queue->front == queue->rear) {
        printf("queue has no element backup to empty\n");
        queue->front = -1;
        queue->rear = -1;
    } else {
        queue->front = (queue->front +1)%MAX_SIZE;
    }

    return item;
}

int peek(Queue* queue) {
    if(isEmpty(queue)) {
        fprintf(stderr,"queue is empty. \n");
        return -1;
    }
    return queue->data[queue->front];
}


int testbasicQueueStaticArray(int agrc, char *argv[]) {
    {
        Queue testqueue = {
            .front = -1,
            .rear = -1,
        };
        Queueinit(&testqueue);

        for(int i = 0; i < 2000; i++) {
            enqueue(&testqueue,200+i);
            dequeue(&testqueue);
        }

        enqueue(&testqueue,1001);
        enqueue(&testqueue,1002);
        enqueue(&testqueue,1003);
        printf("dequeue item:%d \n", dequeue(&testqueue));
        printf("dequeue item:%d \n", dequeue(&testqueue));
        printf("dequeue item:%d \n", dequeue(&testqueue));
        printf("dequeue item:%d \n", dequeue(&testqueue));
        printf("peek queue element: %d queue size:%d\n", peek(&testqueue),QueueSize(&testqueue));
    }

}
单链表实现Queue

单链表实现Queue的基本原理:

  • 建立一个单链表,包含指向队列头的指针queue->front 和指向队列尾的指针queue->rear

  • enqueue时,首先为新元素分配空间,然后插入到单链表的尾部,用queue->rear指向它

  • dequeue时,首先返回queue->front指向的节点内容,然后free掉queue->front节点,queue->front指向顺序的后一个节点

    参考代码如下:

c 复制代码
struct node {
    int data;
    struct node *next;
};

typedef struct {
    struct node *front;
    struct node *rear;
}Queue;

static int empty(Queue* queue){
    return (queue->front == NULL);
}

static void initQueue(Queue* queue) {
    queue->front = queue->rear = NULL;
}

static void push(Queue* queue, int value) {
    struct node *pnode;
    pnode = (struct node*)malloc(sizeof(struct node));
    if(pnode == NULL) {
        printf("malloc node failed!.\n");
        exit(1);
    }
    pnode->data = value;
    pnode->next = NULL;

    if(empty(queue)) {
        queue->front = pnode;
        queue->rear = pnode;
    } else {
        queue->rear->next= pnode;
        queue->rear = pnode;
    }
}

static int pop(Queue* queue) {
    if (empty(queue))
    {
        printf("Queue Underflow. Unable to remove.\n");
        exit(1);
    }
    int item;
    struct node *p = queue->front;
    item = queue->front->data;
    queue->front = queue->front->next;
    if (queue->front == NULL) /* Queue contained only one node */
        queue->rear = NULL;

    free(p);
    return item;
}

static int peek(Queue* queue) {
    if (empty(queue))
    {
        printf("Queue Underflow. Unable to remove.\n");
        exit(1);
    }
    return queue->front->data;
}

static int queueSize(Queue* queue){
    struct node *p = queue->front;
    int count = 0;
    if(empty(queue)){
        return 0;
    }

    do {
        p = p->next;
        count++;
    }while(p != NULL);

    return count;
}



int testbasicQueueImplsingleLinkedList(int agrc, char *argv[]) {
    {
        Queue testqueue;
        int qsize = 0;
        initQueue(&testqueue);
        push(&testqueue, 10);
        printf("queue size: %d. \n", queueSize(&testqueue));

        push(&testqueue, 101);
        push(&testqueue, 102);
        push(&testqueue, 103);
        push(&testqueue, 104);
        printf("queue size: %d. \n", queueSize(&testqueue));

        printf("pop value: %d queue size: %d. \n", pop(&testqueue), qsize);

        qsize = queueSize(&testqueue);
        printf("pop value: %d queue size: %d. \n", pop(&testqueue), qsize);

        qsize = queueSize(&testqueue);
        printf("pop value: %d queue size: %d. \n", pop(&testqueue), qsize);

        qsize = queueSize(&testqueue);
        printf("pop value: %d queue size: %d. \n", pop(&testqueue), qsize);

        printf("queue size: %d. \n", queueSize(&testqueue));
        printf("peek value: %d  \n", peek(&testqueue));
        printf("queue size: %d. \n", queueSize(&testqueue));

    }
    return 1;
}
相关推荐
tainshuai4 分钟前
用 KNN 算法解锁分类的奥秘:从电影类型到鸢尾花开
算法·分类·数据挖掘
Coovally AI模型快速验证6 小时前
农田扫描提速37%!基于检测置信度的无人机“智能抽查”路径规划,Coovally一键加速模型落地
深度学习·算法·yolo·计算机视觉·transformer·无人机
pusue_the_sun6 小时前
数据结构:二叉树oj练习
c语言·数据结构·算法·二叉树
RaymondZhao347 小时前
【全面推导】策略梯度算法:公式、偏差方差与进化
人工智能·深度学习·算法·机器学习·chatgpt
zhangfeng11337 小时前
DBSCAN算法详解和参数优化,基于密度的空间聚类算法,特别擅长处理不规则形状的聚类和噪声数据
算法·机器学习·聚类
啊阿狸不会拉杆8 小时前
《算法导论》第 32 章 - 字符串匹配
开发语言·c++·算法
小学生的信奥之路8 小时前
洛谷P3817题解:贪心算法解决糖果分配问题
c++·算法·贪心算法
你知道网上冲浪吗9 小时前
【原创理论】Stochastic Coupled Dyadic System (SCDS):一个用于两性关系动力学建模的随机耦合系统框架
python·算法·数学建模·数值分析
地平线开发者10 小时前
征程 6 | PTQ 精度调优辅助代码,总有你用得上的
算法·自动驾驶
Tisfy11 小时前
LeetCode 837.新 21 点:动态规划+滑动窗口
数学·算法·leetcode·动态规划·dp·滑动窗口·概率