目录
前言:
大家好!今天给大家带来的数据结构中的队列,希望这篇对大家能有帮助。
队列是一种只允许在一端进行插入数据操作另一端进行删除数据操作的特殊线性表。
队列是具有先进先出 FIFO(First In First Out)特性的线性表。
队头:进行删除数据的一端。
队尾:进行插入数据的一端。

因为队列是线性表的一种,所以队列有顺序存储结构和链式存储结构。
队列的顺序存储结构是通过数组来实现的。具体实现方式是用一个数组来存储队列中的元素,并且使用两个指针分别指向队列的头部和尾部。
- #define MAXSIZE 20
- typedef struct
- {
- int data[MAXSIZE];
- int front,rear;//一个为队头指针,一个为队尾指针
- }queue;
初始状态时,对头指针与队尾指针均指向第一个元素:queue->front==queue->rear==0;
入队操作:将元素插入到队列的尾部,并将尾指针后移一位。
出队操作:将头指针指向的元素出队,并将头指针后移一位。

由上图此时该数组还未放满元素,如果在加入F元素的化却会失败,因为rear=5,尾指针已经达到了队列的最大长度,但该队列还未放满,所以这种情况被称为:假溢出。
为了解决假溢出而导致的队列的空间浪费的问题,我们使用了循环队列。
队列的头尾相接的顺序存储结构称为循环队列。环形队列可以使用数组实现,也可以使用循环链表实现。这里我们用数组实现。

由上图我们发现,当队列为空时和队列为满时,front=rear,这时当rear==front时,该是判满还是判空呢?
解决方案:
方案一:设置一个计数器,开始时计数器设为0,新元素入队时,计数器加1,元素出队,计数器减1。当计数器==MAXSIZE时,队满;计数器==0时,队空。
这里我们主要讲第二种方法。
方案二:保留一个元素空间,当队尾指针指的空闲单元的后继单元是队头元素所在单元时,队满。
当front指针指向最后一个时,我们如何将front=0呢?
这可以利用除法取余运算(%)来实现。
①队首指针进1:Q->front = (Q->front + 1) % MAXSIZE。
②队尾指针进1:Q->rear = (Q->rear + 1) % MAXSIZE。
③队列长度:(Q->rear - Q->front + MAXSIZE) % MAXSIZE。
- typedef int ElemType; //ElemType的类型根据实际情况而定,这里假定为int
- #define MAXSIZE 20 //定义元素的最大个数
- /*循环队列的顺序存储结构*/
- typedef struct{
- ElemType data[MAXSIZE];
- int front; //头指针
- int rear; //尾指针,若队列不空,指向队列尾元素的下一个位置
- }SqQueue;
- int Init_SeQueue(SeQueue *Q)
- {
- Q=(SeQueue *)malloc(sizeof(SeQueue));
- if(Q!=NULL)
- {
- Q->front=0;
- Q->rear=0;
- }
- return 1;
- }
- int SeQueue_Empty(SeQueue *Q)
- {
- return Q->rear==Q->front;
- }
- int QueueLength(SeQueue *Q)
- {
- return (Q->rear-Q->front+MAXSIZE)%MAXSIZE;
- }
- int Enter_SeQueue(SeQueue *Q,ElemType e)
- {
- if(SeQueue_Full(Q))
- {
- return 0;
- }
-
- Q->data[Q->rear]=e;
- Q->rear=(Q->rear+1)%MAXSIZE;
- return 1;
- }
- int SeQueue_Full(SeQueue *Q)
- {
- return (Q->rear+1)%MAXSIZE==Q->front;
- }
- int Delete_SeQueue(SeQueue *Q,ElemType e)
- {
- if(SeQueue_Empty(Q))
- {
- return 0;
- }
-
- e=Q->data[Q->front];
- Q->front=(Q->front+1)%MAXSIZE;
- return 1;
- }

链队列的分析与顺序队列的分析类似,都需要借用头指针和尾指针,但是为了方便使用我们创建另一个结构体来放置头指针和尾指针以及队列中元素个数。
- typedef int QdataType;
- 链式结构:表示队列
- typedef struct queuenode
- {
- struct queuenode* next;//下个元素的地址
- QdataType val;//队列的信息
- }QNode;
- 队列的结构
- typedef struct queue
- {
- QNode* phead;
- QNode* ptail;
- int size;//对列中的元素个数
- }queue;
- //初始化
- void QueueInit(queue* pst)
- {
- assert(pst);
- pst->phead = NULL;
- pst->ptail = NULL;
- pst->size = 0;
- }
- void QueueDestory(queue* pst)
- {
- assert(pst);
- QNode* cur = pst->phead;
- while (cur)
- {
- QNode* Next = cur->next;
- free(cur);
- cur = Next;
- }
- pst->phead = pst->ptail = NULL;
- pst->size = 0;
- }
- void QueuePush(queue* pst, QdataType x)
- {
- assert(pst);
- QNode* NewQNode = (QNode*)malloc(sizeof(QNode));
- //判断申请空间是否有效
- if (NewQNode = NULL)
- {
- perror("malloc fail");
- return ;
- }
- NewQNode->next = NULL;
- NewQNode->val = x;
- //此时队列为空
- if (pst->size = 0)
- {
- pst->phead = pst->ptail = NewQNode;
- }
- else
- {
- pst->ptail->next = NewQNode;
- pst->ptail = NewQNode;
- }
- pst->size++;
- }
- void QueuePop(queue* pst)
- {
- assert(pst);
- assert(pst->ptail);
- //只有一个节点时
- if (pst->phead = pst->ptail)
- {
- free(pst->phead);
- pst->phead = pst->ptail = NULL;
- }
- //多个节点时
- else
- {
- QNode* next = pst->phead->next;
- free(pst->phead);
- pst->phead = next;
- }
- pst->size--;
- }
- QdataType QueueFront(queue* pst)
- {
- assert(pst);
- assert(pst->ptail);
- return pst->phead->val;
- }
- QdataType QueueBack(queue* pst)
- {
- assert(pst);
- assert(pst->ptail);
- return pst->ptail->val;
- }
- int QueueSize(queue* pst)
- {
- assert(pst);
- return pst->size;
- }
- bool QueueEmpty(queue* pst)
- {
- assert(pst);
- return pst->size==0;
- }
- typedef struct {
- int *a;
- int phead;
- int tail;
- int k;
- } MyCircularQueue;
-
-
- MyCircularQueue* myCircularQueueCreate(int k) {
- MyCircularQueue*pst=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
- pst->a=(int*)malloc(sizeof(int)*(k+1));
- pst->phead=0;
- pst->tail=0;
- pst->k=k;
- return pst;
- }
- bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
- return obj->tail==obj->phead;
- }
-
- bool myCircularQueueIsFull(MyCircularQueue* obj) {
- return (obj->tail+1)%(obj->k+1)==obj->phead;
- }
-
- bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
- if(myCircularQueueIsFull(obj))
- return false;
- obj->a[obj->tail]=value;
- obj->tail++;
- obj->tail%=(obj->k+1);
- return true;
-
- }
-
- bool myCircularQueueDeQueue(MyCircularQueue* obj) {
- if(myCircularQueueIsEmpty(obj))
- {
- return false;
- }
- else{
- ++obj->phead;
- obj->phead%=(obj->k+1);
- return true;
- }
- }
-
- int myCircularQueueFront(MyCircularQueue* obj) {
- if(myCircularQueueIsEmpty(obj))
- {
- return -1;
- }
- return obj->a[obj->phead];
- }
-
- int myCircularQueueRear(MyCircularQueue* obj) {
- if(myCircularQueueIsEmpty(obj))
- {
- return -1;
- }
- return obj->tail==0?obj->a[obj->k]:obj->a[obj->tail-1];
- }
- void myCircularQueueFree(MyCircularQueue* obj) {
- free(obj->a);
- free(obj);
- }
仅使用两个栈我们就可以实现先入先出队列:
实现队列最重要的是实现先进先出原则,即我们用栈实现队列最重要的是完成插入与取出,这里我们创建两个栈
一个为:puspst专门用来插入数据。
一个为:popst专门用来出数据。
当我们先后插入1 ,2, 3, 4进入pushst栈时,再将pushst栈的元素插入popst栈中,这时再出栈时的顺序就是1 ,2, 3, 4
- typedef int STDataType;
-
- typedef struct Stack
- {
- STDataType* a;
- int top;
- int capacity;
- }ST;
- void STInit(ST* pst)
- {
- assert(pst);
-
- pst->a = NULL;
- // top指向栈顶数据的下一个位置
- pst->top = 0;
-
- // top指向栈顶数据
- //pst->top = -1;
-
- pst->capacity = 0;
- }
-
- void STDestroy(ST* pst)
- {
- assert(pst);
-
- free(pst->a);
- pst->a = NULL;
- pst->top = pst->capacity = 0;
- }
-
- // 入栈 出栈
- void STPush(ST* pst, STDataType x)
- {
- assert(pst);
-
- // 扩容
- if (pst->top == pst->capacity)
- {
- int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
- STDataType* tmp = (STDataType*)realloc(pst->a, newcapacity * sizeof(STDataType));
- if (tmp == NULL)
- {
- perror("realloc fail");
- return;
- }
-
- pst->a = tmp;
- pst->capacity = newcapacity;
- }
-
- pst->a[pst->top] = x;
- pst->top++;
- }
-
- void STPop(ST* pst)
- {
- assert(pst);
- assert(pst->top > 0);
-
- pst->top--;
- }
- // 取栈顶数据
- STDataType STTop(ST* pst)
- {
- assert(pst);
- assert(pst->top > 0);
-
- return pst->a[pst->top - 1];
- }
-
- // 判空
- bool STEmpty(ST* pst)
- {
- assert(pst);
-
- return pst->top == 0;
- }
-
- // 获取数据个数
- int STSize(ST* pst)
- {
- assert(pst);
-
- return pst->top;
- }
-
-
- typedef struct {
- ST pushst;
- ST popst;
- } MyQueue;
-
-
- MyQueue* myQueueCreate() {
- MyQueue*obj=( MyQueue*)malloc(sizeof( MyQueue));
- STInit(&(obj->pushst));
- STInit(&(obj->popst));
- return obj;
- }
-
- void myQueuePush(MyQueue* obj, int x) {
- STPush((&(obj->pushst)),x);
- }
-
- int myQueuePeek(MyQueue* obj) {
- if(STEmpty(&(obj->popst)))
- {
- while(!(STEmpty(&(obj->pushst))))
- {
- int top=STTop(&(obj->pushst));
- STPush((&(obj->popst)),top);
- STPop(&(obj->pushst));
- }
- }
- return STTop(&(obj->popst));
- }
- int myQueuePop(MyQueue* obj) {
- int front=myQueuePeek(obj);
- STPop(&(obj->popst));
- return front;
- }
- bool myQueueEmpty(MyQueue* obj) {
- return STEmpty(&(obj->pushst))&&STEmpty(&(obj->popst));
- }
-
- void myQueueFree(MyQueue* obj) {
- STDestroy(&(obj->pushst));
- STDestroy(&(obj->popst));
- free(obj);
- }