3.队列

队列简介

队列是一种先进先出FIFO,First-In-First-Out的线性表,通常用链表或者数组来实现。队列只能在队尾插入元素,只能在队首删除元素。

队列,第一个元素叫做队首,最后一个元素叫做队尾。队首元素删除叫做出队,新元素加入队尾叫做入队。队列有一个很重要的性质,就是 先进先出,First In First Out(FIFO)。

我们在构造队列时,需要用两个变量来记录队首和队尾的位置,设置这两个变量有利于我们去维护队列的次序性。

循环队列

只记录头尾的数组队列容易造成假溢出,当记录尾部位置的tail达到队列的上限后就不能再插入了,此时再插入就意味着溢出。但是tail达到上限后并不是要插入的元素真的“无处可放”了。为了解决这种问题,我们用数组实现队列的方式均是以“循环队列”的方式实现的。

循环队列,顾名思义,就是以循环的方式来存储队列。当队尾标记tail到达队列上限后,如果队列内的元素没有达到上限,就跳转到数组的开始位置,也就是 0 的位置,队首标记到达队列上限也采取同样的处理。通过这样的方法,我们就能够最大化利用内存空间,避免“假溢出”的情况出现。

用数组实现循环队列的基本操作
/*************************************************************************
  > File Name: 3.queue.c
  > Author: 陈杰
  > Mail: 15193162746@163.com
  > Created Time: 2021年03月30日 星期二 09时31分56秒
  > 数组实现循环队列的基本操作
************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include <time.h>
typedef struct Queue{
    int *data;
    int head,tail,length,size;
}Queue;
/*
* 队列初始化
* @param n: 队列初始化大小
* */
Queue *init(int n) {
    Queue *q = (Queue *)malloc(sizeof(Queue));
    q->data = (int *)malloc(sizeof(int) * n);
    q->head = q->tail = q->length;
    q->size = n;
    return q;
}
/*
* 判空
* @param q: 要操作的队列指针
* **/
int empty(Queue *q) {
    return q->length == 0;                          // 判断队列长度是否为零
}
/*
* 扩容
* @param q: 要操作的队列指针
* */
int expand(Queue *q) {
    if(q == NULL) return 0;
    int extr_size = q->size;
    int *p = NULL;
    while(extr_size) {                              // 空间使用过大,可能造成申请失败
        p = (int *)malloc(sizeof(int) * (q->size + extr_size));
        if(p) break;
        extr_size >>= 1;                            // 扩容大小减半
    }
    if(p == NULL) return 0;
    for(int j = 0; j < q->length; j++) p[j] = q->data[(q->head + j) % q->size];
    free(q->data);
    q->data = p;
    q->head = 0;
    q->tail = q->length;
    q->size += extr_size;
}
/*
* 入队
* @param q: 要操作的队列指针
* @param val: 要入队的新元素值
* */
int push(Queue *q, int val) {
    if(q == NULL) return 0;                         // 判断队列是否存在
    if(q->tail == q->length && !expand(q)) return 0;// 队列已满且扩容失败
    q->data[q->tail++] = val;
    if(q->tail == q->size) q->tail = 0;             // tail值达到size时赋值为0
    // q->tail = q->tail % q->size;
    q->length++;
    return 1;
}
/*
* 出队
* @param q: 要操作的队列指针
* */
int pop(Queue *q) {
    if(q == NULL || empty(q)) return 0;             // 队列不存在或者为空
    q->head++;
    if(q->head == q->size) q->head = 0;             // head值达到size值时赋值为0
    // q->head = q->head % q->size;
    q->length--;
    return 1;
}
/*
* 获得队首元素值
* @param q: 要操作的队列指针
* */
int front(Queue *q) {
    return q->data[q->head];
}
/*
* 队列销毁
* @param q: 要操作的队列指针
* */
void clear(Queue *q) {
    if(q == NULL) return;
    free(q->data);
    free(q);
}
/*
* 打印队列
* @param q: 要操作的队列指针
* */
void output(Queue *q) {
    printf("Queue:[");
    int i = q->head;
    do{
        printf("%d ", q->data[i]);
        i = (i + 1) % q->size;
    }while(i != q->tail);
    printf("]\n");
}
int main() {
    srand(time(0));
    #define MAX_OP 20
    Queue *q = init(MAX_OP);
    for(int i = 0; i < MAX_OP; i++) {
        int op = rand() % 4;
        int val = rand() % 100;
        if(op) printf("push %d to Queue = %d\n", val, push(q, val));
        else if(!empty(q)) printf("%d pop out from Queue", front(q)),printf(" = %d\n",pop(q));
        else printf("fail to pop a item!\n");
        output(q),printf("\n");
    }
    clear(q);
    #undef MAX_OP
    return 0;
}
链表实现队列的基本操作
/*************************************************************************
  > File Name: 3.queue_link.c
  > Author: 陈杰
  > Mail: 15193162746@163.com
  > Created Time: 2021年03月30日 星期二 10时26分51秒
  > 用链表实现队列
************************************************************************/
#include<stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct Node {
    int data;
    struct Node *next;
}Node;
typedef struct Queue {
    int length;
    Node *head, *tail;
}Queue;
/*
* 获取一个赋值结点
* @param val: 新节点的值
* */
Node *getNode(int val){
    Node *node = (Node *)malloc(sizeof(Node));
    node->data = val;
    node->next = NULL;
    return node;
}
/*
* 初始化队列
* */
Queue *init() {
    Queue *q = (Queue *)malloc(sizeof(Queue));
    q->length = 0;
    q->head = NULL;
    q->tail = NULL;
    return q;
}
/*
* 队列判空
* @param q: 待处理队列的指针
* **/
int empty(Queue *q) {
    return q->length == 0;
}
/*
* 入队
* @param q: 待处理队列的指针
* @param val: 待入队元素的值
* */
int push(Queue *q, int val) {
    if(q == NULL) return 0;
    if(empty(q)){
        q->tail = getNode(val);
        q->head = q->tail;
    }else {
        q->tail->next = getNode(val);
        q->tail = q->tail->next;
    }
    q->length++;
    return 1;
}
/*
* 出队
* @param q: 待处理队列的指针
* */
int pop(Queue *q) {
    if(q == NULL || empty(q)) return 0;
    Node *delete_node = q->head;
    q->head = q->head->next;
    if(q->head == NULL) q->tail = NULL;
    free(delete_node);
    q->length--;
    return 1;
}
/*
* 获取队首元素值
* @param q: 待处理队列的指针
* */
int front(Queue *q) {
    return q->head->data;
}
/*
* 清理队列
* @param q: 待处理队列的指针
* */
void clear(Queue *q) {
    if(q == NULL) return;
    while(q->head) {
        Node *delete_node = q->head;
        q->head = q->head->next;
        free(delete_node);
    }
    free(q);
}
/*
* 队列打印
* @param q: 待处理队列的指针
* */
void output(Queue *q) {
    printf("Queue:[");
    Node *p = q->head;
    while(p) {
        printf("%d ",p->data);
        p = p->next;
    }
    printf("]\n");
}
int main() {
    srand(time(0));
    #define MAX_OP 10
    Queue *q = init();
    for(int i = 0; i < MAX_OP; i++) {
        int val = rand() % 100;
        int op = rand() % 4;
        if(op) printf("push %d to Queue = %d\n", val, push(q, val));
        else if(!empty(q)) printf("%d pop out from Queue", front(q)),printf(" = %d\n",pop(q));
        else printf("fail to pop a item!\n");
        output(q),printf("\n");
    }
    clear(q);
    #undef MAX_OP
    return 0;
}
队列在做题过程中的简单实现
/*************************************************************************
  > File Name: 3.queue_temp.c
  > Author: 陈杰
  > Mail: 15193162746@163.com
  > Created Time: 2021年03月30日 星期二 11时00分14秒
  队列在刷题过程中的简单实现
************************************************************************/
#include<stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX_OP 20
int queue[MAX_OP];
int head, tail;
/*
* 打印队列
* (为了查看方便,时间操作中并不需要)
* */
void output() {
    printf("Queue:[");
    for(int i = head; i < tail; i++) printf("%d ", queue[i]);
    printf("]\n");
}
int main() {
    srand(time(0));
    for(int i = 0; i < MAX_OP; i++) {
        int val = rand() % 100;
        int op = rand() % 4;
        if(op) {                                                // 入栈操作
            queue[tail++] = val;
            printf("push %d to Queue = %d\n", val, 1);
        }else {                                                 // 出栈操作
            printf("%d pop out from Queue = 1\n", queue[head++]);
        }
          output(),printf("\n");
      }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值