赞
踩
队列是一种操作受限的线性表,它只允许从队头出队,从队尾入队,就像生活中的排队一样。双端队列放宽了这种限制,它可以从队头出队或入队,也可以从队尾出队或入队。
一般队列:
双端队列:
双端队列可以从两端进行出队和入队,也可以对一种操作进行限制,例如,入队受限(一端入队)的双端队列和出队(一端出队)的双端队列。
双端队列可以使用循环数组来实现,也可以使用双链表来实现,下面给出双端队列的循环数组实现,链表实现的原理与队列的实现也是类似的,但由于双端队列可能会从尾部删除结点,所以为了效率,使用能够找到前驱结点的双链表。
循环数组实现:
- #define MAX_SIZE 20
-
- //双端队列可以使用数组或链表实现,使用双链表应该比较简单,但这里使用循环数组来实现双端队列的增删改查等操作
- typedef struct DoubleQueue {
- int front;//头指针
- int rear;//尾指针
- int numofele;//队列中的元素数量
- int arr[MAX_SIZE];//假设队列中只存储非负整数,最大容量为MAX_SIZE
- }DoubleQueue;
-
- //创建队列
- DoubleQueue* CreatQueue() {
-
- DoubleQueue* q = (DoubleQueue*)malloc(sizeof(DoubleQueue));
- if (q == NULL) {
- perror("malloc");
- return NULL;
- }
- //假设队列的队头入队和队尾入队都是从数组下标为0处开始
- q->front = q->rear = -1;
- q->numofele = 0;
- return q;
- }
-
- //清空队列
- void ClearQueue(DoubleQueue* q) {
- if (q == NULL) {
- printf("队列不存在\n");
- return;
- }
- //清空队列时,只需要改变头尾指针和队列中元素的数量即可
- q->front = q->rear = -1;
- q->numofele = 0;
- }
-
- //销毁队列
- void DestoryQueue(DoubleQueue* q) {
- if (q == NULL) {
- printf("队列不存在\n");
- return;
- }
- //由于队列只使用了一次动态内存分配,所以直接free
- free(q);
- q = NULL;
- }
-
- //判断队列是否为空
- bool IsEmpty(DoubleQueue* q) {
- if (q == NULL) {
- printf("队列不存在\n");
- return true;//返回true为了防止在队列为空时的操作引用空指针
- }
- return q->numofele == 0;
- }
-
- //判断队列是否为满
- bool IsFull(DoubleQueue* q) {
- if (q == NULL) {
- printf("队列不存在\n");
- return true;//为了防止在队列不满情况下对空指针的操作
- }
- return q->numofele == MAX_SIZE;
- }
-
- //返回队头元素
- int GetHead(DoubleQueue* q) {
- if (q == NULL) {
- printf("队列不存在\n");
- return -1;//假设队列中存储非负整数,返回-1表示错误
- }
- if (IsEmpty(q)) {
- printf("队列为空,不存在队头元素\n");
- return -1;
- }
- return q->arr[q->front];
- }
-
- //返回队尾元素
- int GetTail(DoubleQueue* q) {
- if (q == NULL) {
- printf("队列不存在\n");
- return -1;//假设队列中存储非负整数,返回-1表示错误
- }
- if (IsEmpty(q)) {
- printf("队列为空,不存在队尾元素\n");
- return -1;
- }
- return q->arr[q->rear];
- }
-
- //获得从队头入队的下标
- int GetHeadIndex(DoubleQueue* q, int size) {
- if (IsEmpty(q)) {
- q->rear = 0;//如果从对头入队的是第一个元素,则需要将队头队尾指针都设为0
- return 0;
- }
- if (q->front - 1 < 0) {
- return (q->front - 1) + size;
- }
- else {
- return q->front - 1;
- }
- }
-
- //从队头入队
- void EnqueueFromHead(DoubleQueue* q, int k) {
- if (q == NULL) {
- printf("队列不存在\n");
- return;
- }
- if (IsFull(q)) {
- printf("队列已满,无法入队\n");
- return;
- }
- q->front = GetHeadIndex(q, MAX_SIZE);
- q->numofele++;
- q->arr[q->front] = k;
- }
-
- //得到从队尾入队的下标
- int GetTailIndex(DoubleQueue* q, int size) {
- if (IsEmpty(q)) {
- q->front = 0;
- return 0;
- }
- return (q->rear + 1) % size;
- }
-
- //从队尾入队
- void EnqueueFromTail(DoubleQueue* q, int k) {
- if (q == NULL) {
- printf("队列不存在\n");
- return;
- }
- if (IsFull(q)) {
- printf("队列已满,无法入队\n");
- return;
- }
- q->rear = GetTailIndex(q, MAX_SIZE);
- q->numofele++;
- q->arr[q->rear] = k;
- }
-
- //从队头出队
- int DequeueFromHead(DoubleQueue* q) {
- if (q == NULL) {
- printf("队列不存在\n");
- return -1;
- }
- if (IsEmpty(q)) {
- printf("队列为空,无法出队\n");
- return -1;
- }
- q->numofele--;
- int ret = q->arr[q->front];
- q->front = (q->front + 1) % MAX_SIZE;
- return ret;
- }
-
- //从队尾出队
- int DequeueFromTail(DoubleQueue* q) {
- if (q == NULL) {
- printf("队列不存在\n");
- return -1;
- }
- if (IsEmpty(q)) {
- printf("队列为空,无法出队\n");
- return -1;
- }
- int ret = q->arr[q->rear];
- q->numofele--;
- if (q->rear - 1 < 0) {
- q->rear = q->rear - 1 + MAX_SIZE;
- }
- else {
- q->rear = q->rear - 1;
- }
- return ret;
- }
-
- //从队头开始打印队列数据
- void Print(DoubleQueue* q) {
- if (q == NULL) {
- printf("队列不存在\n");
- return;
- }
- if (IsEmpty(q)) {
- printf("队列为空,无法打印\n");
- return;
- }
- int count = q->numofele;
- int p = q->front;
- while (count--) {
- printf("%d ", q->arr[p]);
- p = (p + 1) % MAX_SIZE;
- }
- printf("\n--------------------------\n");
- }
测试代码:
- #include <stdio.h>
- #include <stdbool.h>
- #include <stdlib.h>
-
- int main() {
-
- DoubleQueue* q = CreatQueue();
-
- //从队头入队10个元素
- for (int i = 0; i < 10; i++) {
- EnqueueFromHead(q, i);
- }
- Print(q);
-
- for (int i = 10; i < 20; i++) {
- EnqueueFromTail(q, i);
- }
- Print(q);
-
- printf("从队头删除的元素是 %d\n", DequeueFromHead(q));
- Print(q);
- printf("从队尾删除的元素是:%d\n", DequeueFromTail(q));
- Print(q);
-
- printf("队头元素是:%d\n", GetHead(q));
- printf("队尾元素是:%d\n", GetTail(q));
-
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。