数据结构复习之实现队列

167 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情

这里实现的是循环队列的代码。相关操作如下:

  • 初始化队列
  • 销毁队列
  • 入队:如果容量满了,要进行扩容操作。开辟新空间,然后遍历老空间,将之前的数据搬过来
  • 出队
  • 获取队首元素
  • 打印队列

//
// 实现循环队列
// 循环队列支持动态扩容操作
//
#include <stdio.h>
#include <stdlib.h> // 进行动态的内存分配与释放

//定义队列结构
typedef struct queue {
    int *data; // 数据域,动态的,所以存指针
    int cap, size, front, rear; // cap: 容量上限  size:元素数量(可有可无) front:队首元素  rear:队尾元素的下一个元素
} queue;

// 创建:初始化,初始化容量上限为n的循环队列
queue *init_queue(int n) {
    queue *q = (queue *) malloc(sizeof (queue)); // 初始化队列的结构,需要申请空间
    q->data = (int *) malloc(sizeof (int) * n);// 手动申请队列中的数据域空间
    q->cap = n, q->size = 0;
    q->front = 0, q->rear = 0;
    return q;
}

// 销毁队列:先销毁它的数据域,在销毁它本身
void delete_queue(queue *q) {
    free(q->data);
    free(q);
}
// 入队:涉及扩容,不能像之前直接用realloc()扩容,需要重新申请一片空间,然后把元素一个一个的搬过去
int push(queue *q, int x) {
    // 判断队列是否满了
    // ((q->rear + q->cap) - q->front) % q->cap + 1 == q->cap
    //   (q->rear + 1) % q->cap == q->front   √
    if (q->size + 1 == q->cap) { //! 容量满了,扩容
        // 扩容操作:循环队列满了,需要扩容
        int *p = (int *) malloc(sizeof (int) * q->cap * 2);
        //! i: 遍历老空间, j: 遍历新空间,将数据手动移动
        for (int i = q->front, j = 0; j < q->size; i = (i + 1) % q->cap, j++) {
            p[j] = q->data[i];
        }
        q->cap *= 2;
        q->front = 0;
        q->rear = q->size;
        int *t = q->data;
        q->data = p; //! 更改,替换数据域指针为新空间
        free(t); //! 把原有空间释放
    }
    q->data[q->rear] = x;
    q->rear++;
    q->rear %= q->cap;
    q->size++;
    return 0;
}
// 出队
int pop(queue * q) {
    // 判断是否为空
    // q->front == q->rear
    if (q->size == 0) {
        return  -1;
    }
    q->front++;
    q->front %= q->cap;
    q->size--;
    return 0;
}

// 获取队首元素
int get_front(queue * q) {
    if (q->size == 0) {
        return  -1;
    }
    return q->data[q->front]; // 返回数据域中队首元素下标对应的元素
}

// 打印队列
void show_queue(queue *q) {
    printf("size = %d, cap = %d\n", q->size, q->cap);
    for(int i = q->front; i != q->rear; i = (i + 1) % q->cap) {
        printf("%d ",q->data[i]);
    }
    printf("\n--------------------------------\n");
}


int main() {
    int n, m; // n: 操作次数  m:容量上限
    scanf("%d%d", &n, &m);
    queue *q = init_queue(m);
    for (int i = 0; i < n; i++) {
        int a;
        scanf("%d", &a); // 入队x   0:入队  1:出队  2:获取队首元素
        if (a == 0) {
            scanf("%d", &a);
            push(q, a);
        } else if (a == 1) {
            pop(q);
        } else {
            printf("front -> %d\n", get_front(q));
        }
        show_queue(q);
    }
    delete_queue(q);
    return 0;
}

  • 顺序队列
  • 链式队列
    • 单链表,保留尾指针
    • 循环链表