当前位置:网站首页>Queue队列的实现
Queue队列的实现
2022-06-21 10:43:00 【iEucliwood】
队列的基本概念及讨论
队列只能在表的一端进行插入,这一端叫作队尾,而在另一端进行删除,这一端叫队头。这样的结构有先进先出FIFO(first in first off)的特点,也可以是后进后出。链表可以用来实现队列或者循环队列,数组一般用来实现循环队列,因为数组在前端的插入或删除操作花费O(N)时间。队列的应用有很多,比如打印机是按照作业到达的顺序排列起来的,生活中的排队是先到的先处理。
队列的基本实现
1.不循环队列
基本思想
如果用单链表实现,则除了链表结构外还需要多声明一个队列结构来指示在链表中的队头位置和队尾位置,这样就可以使队列的入队出队只花费O(1)时间。若用带头双向循环链表则可以选择不用声明队列结构,因为入队出队也只花费O(1)时间。这里我们用单链表实现
结构声明和函数声明
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int DataType;
typedef struct ListNode* PtrToNode;
typedef PtrToNode Position;
typedef struct Queue* Queue;
struct ListNode
{
DataType data;
PtrToNode next;
};
struct Queue
{
Position front;
Position rear;
};
Queue QueueCreate();
void DeQueue(Queue q);
void EnQueue(Queue q, DataType x);
DataType QueueFront(Queue q);
DataType QueueRear(Queue q);
int IsEmpty(Queue q);
int QueueSize(Queue q);
void QueueDestroy(Queue q);
void QueuePrint(Queue q);
void QueueDestroy(Queue q);队列创建:
Queue QueueCreate()
{
Queue q = (Queue)malloc(sizeof(struct Queue));
if (q == NULL)
{
printf("out of spaces!\n");
exit(-1);
}
q->front = NULL;
q->rear = NULL;
return q;
}入队和出队:
void EnQueue(Queue q, DataType x)
{
assert(q);
PtrToNode newNode = (PtrToNode)malloc(sizeof(struct ListNode));
if (newNode == NULL)
{
printf("out of spaces!\n");
exit(-1);
}
newNode->data = x;
newNode->next = NULL;
if (IsEmpty(q))
{
q->front = q->rear = newNode;
}
else
{
q->rear->next = newNode;
q->rear = newNode;;
}
}
void DeQueue(Queue q)
{
assert(q);
if (IsEmpty(q))
return;
Position head = q->front;
q->front = q->front->next;
if (q->front == NULL)
q->rear = NULL;
free(head);
}出队的函数编写需要非常仔细,稍不注意可能就会漏掉对q->rear的更新,最后需要判断队头是否走到了空,如果队头走到了空,那么队尾也应该置为空 否则就会变成非法指针。
返回队头和队尾:
DataType QueueFront(Queue q)
{
assert(q);
assert(!IsEmpty(q));
return q->front->data;
}
DataType QueueRear(Queue q)
{
assert(q);
assert(!IsEmpty(q));
return q->rear->data;
}判空和返回大小
判断空可以有几种方法,可以只判断队头为空、只判断队尾为空或者判断队头队尾都为空。如果是后面两种写法,那么出队函数若忘记了对q->rear的更新,程序的错误就会在判空函数上得以找到,如果是第一种问题就会较严重,程序的错误很隐蔽,即使忘了更新q->rear,程序也能正常运行。
int IsEmpty(Queue q)
{
return q->front == NULL;
}
int QueueSize(Queue q)
{
assert(q);
Position cur = q->front;
int count = 0;
while (cur)
{
cur = cur->next;
count++;
}
return count;
}打印和销毁:
void QueuePrint(Queue q)
{
assert(q);
while (!IsEmpty(q))
{
printf("%d ", QueueFront(q));
DeQueue(q);
}
printf("\n");
}
void QueueDestroy(Queue q)
{
assert(q);
while (!IsEmpty(q))
{
DeQueue(q);
}
free(q);
}2.循环队列
基本思想
由于链表实现循环队列较为简单,我们来讨论数组的循环队列实现。循环队列是在一定的空间内,循环利用空间,比如一个给定的数组大小为10,front为数组头,rear为数组尾,当入队十次时,队列似乎是满了,下一次入队rear就会到达一个数组外的位置,然而队列中也许只有不到十个元素,因为若干个元素可能已经出队了,所以出队的那些空间又可以利用起来。解决方法是让rear回到数组开头的位置。还有一些问题需要注意,一开始时基准情形rear给定为0,front给定为1。此时表示为空队列,当经过9次入队时,rear=9,再一次入队,rear回到开头rear=0。此时表示满队列。我们发现rear=0,front=1既可以表示空队列也可以表示满队列。出现这种分歧有两种解决方法,第一种是在队列结构中加上size字段,当size为0时表示空队列,size为10时表示满队列。第二种是不让这种情况出现,少存储一个数据,也就是说当队列大小为N时,有N-1个数据时队列就满了。因为如果要让这种情况出现,需要rear绕一圈回到原位置,只要少存一个让rear回不到原位置即可。我们采用第一种方法,第二种在编程中需要格外注意,需要存储k个元素就需要申请k+1的空间。且队列为空时,front是rear的下一个位置,队列为满时,front是rear的下两个位置。
结构声明与函数声明:
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#define MINSIZE (5)
typedef int DataType;
typedef int Position;
typedef struct QueueRecord* Queue;
struct QueueRecord
{
DataType* data;
int front;
int rear;
int capacity;
int size;
};
Queue QueueCreate(size_t size);
void EnQueue(Queue q, DataType x);
void DeQueue(Queue q);
DataType QueueFront(Queue q);
DataType QueueRear(Queue q);
Position NextPosition(Queue q, Position p);
int IsEmpty(Queue q);
int IsFull(Queue q);
void PrintQueue(Queue q);
void QueueDestroy(Queue q);队列创建:
Queue QueueCreate(size_t size)
{
Queue q = (Queue)malloc(sizeof(struct QueueRecord));
if (q == NULL)
{
printf("out of spaces!\n");
exit(-1);
}
q->capacity = size > MINSIZE ? size : MINSIZE;
q->data = (DataType*)malloc(sizeof(DataType) * q->capacity);
if (q->data == NULL)
{
printf("out of spaces!\n");
exit(-1);
}
q->rear = 0;
q->front = 1;
q->size = 0;
return q;
}入队和出队:
void EnQueue(Queue q, DataType x)
{
assert(q);
if (IsFull(q))
{
printf("EnQueue failed! Queue is already full\n");
return;
}
q->rear = NextPosition(q, q->rear);
q->data[q->rear] = x;
q->size++;
}
void DeQueue(Queue q)
{
if (!IsEmpty(q))
{
q->front = NextPosition(q, q->front);
q->size--;
}
}判断空和满:
int IsEmpty(Queue q)
{
return q->size == 0;
}
int IsFull(Queue q)
{
return q->size == q->capacity;
}寻找下一个位置:
Position NextPosition(Queue q, Position p)
{
if (++p == q->capacity)
return 0;
return p;
}返回队头和队尾:
DataType QueueFront(Queue q)
{
assert(q);
return q->data[q->front];
}
DataType QueueRear(Queue q)
{
assert(q);
return q->data[q->rear];
}打印和销毁:
void PrintQueue(Queue q)
{
while (!IsEmpty(q))
{
printf("%d ", QueueFront(q));
DeQueue(q);
}
}
void QueueDestroy(Queue q)
{
assert(q);
free(q->data);
free(q);
}边栏推荐
- Intel和台积电的先进工艺阻力越来越大,中国芯片有望缩短差距
- WPF DataContext 使用
- 使用shapeit进行单倍型分析
- DSP online upgrade (3) -- how to burn two projects in the on-chip flash of a DSP chip
- Where is the cow in Shannon's information theory?
- Introduction to ThreadPoolExecutor
- On the problem of class member variable pollution in the context of one-time concurrence
- 性能优化——图片压缩、加载和格式选择
- MySQL advanced - personal notes
- Positive results of enx-101 clinical 1b study published by English topics
猜你喜欢

The first phase of takin open source training camp is coming! Teach you to complete the full link voltage test hand in hand!

Simple Android weather app (III) -- city management and database operation

New programmers optimize a line of code on Monday and are discouraged on Wednesday?

Matplotlib 绘制圆环图的两种方法!

The memory allocation of the program, the storage of local const and global const in the system memory, and the perception of pointers~

STL summary

WCF restful+jwt authentication

中芯国际据理力争赢了美国诉讼,证明独立自主才能有更长远的发展

Three elements of basic concepts and methods of machine learning

The execution process before executing the main function after the DSP chip is powered on
随机推荐
06. Redis log: the trump card for fast recovery without fear of downtime
Will the thunderstorm of Celsius be the "Lehman moment" in the field of encryption?
Haplotype analysis using shapeit
Prometheus flask exporter usage example
support vector machine
Signal power spectrum estimation
知识点滴 - 什么是加速移动网页(AMP)?
性能优化——图片压缩、加载和格式选择
Classification of ram and ROM storage media
Network multimedia -- linphone correlation analysis -- directory
Financial institutions scramble for "digital employees"; Release of aging service evaluation framework for insurance app
Leader: who uses redis expired monitoring to close orders? Get out of here!
Brief introduction of quality control conditions before genotype filling
The execution process before executing the main function after the DSP chip is powered on
Mqtt of NLog custom target
中部“第一城”,网安长沙以何安网?
MySQL advanced - personal notes
西电AI专业排名超清北,南大蝉联全国第一 | 2022软科中国大学专业排名
How to convert mindspire model to onnx format and use onnxruntime reasoning - development test
Prometheus Flask exporter使用示例