队列的顺序结构实现
队列遵循的是先进先出的规则,我们使用一个定长数组和队头队尾两个指针来完成这个结构。
顺序结构使用结构体来表示,如下:
#define maxsize 100
typedef struct {
int data[maxsize]; // 定长数组存放队列元素
int front, rear; // 队头队尾指针
}Queue;
我这里实现的队列,front指针是一个队头结点,无意义,front+1所在位置才是队伍第一个元素,有点类似链表的头结点~
这里需要明确几个操作状态:
- 初始化:front = rear = 0;
- 进队:队不满,data[ ++ rear] = value;
- 出队:队非空,data[++front] = value,然后返回元素;
循环队列可以保证充分地利用数组空间。我们使用+1取余的方式来循环 front rear指针。
- front ++ -> front = (front + 1) % maxsize
- rear ++ -> rear = (rear + 1 ) % maxsize
- 长度为 (rear - front ) % maxsize
实现代码如下:
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#define MAXSIZE 200
#define ERROR -1
typedef struct QNode* Queue;
typedef struct QNode QNode;
struct QNode{
int data[MAXSIZE];
int rear; // rear所在位置就是刚入队元素的位置
int front; // front的位置表示队头
// 当 rear + 1 % MAXSIZE == front时,队满;
// 当 rear == front 时,队空
// 当删除时,front 向前移动一个位置;
// 当处于边界的时候,可以考虑 + 1 % maxsize 实现循环移动指针的效果。
};
Queue initialQueue(){
Queue Q = (Queue)malloc(sizeof(QNode));
Q->rear=Q->front=0;
return Q;
}
bool addQ(Queue Q,int item){
/*添加元素的方法是:先移动rear指针,然后在rear所指的位置记录数据*/
if(Q->rear + 1 % MAXSIZE == Q->front){
printf("The queue is full \n");
return false;
}
Q->rear = (Q->rear + 1)% MAXSIZE;
Q->data[Q->rear] = item;
return true;
}
int deleteQ(Queue Q){
if(Q->front == Q->rear){
printf("The queue is empty \n");
return ERROR;
}
Q->front = (Q->front + 1) % MAXSIZE;
return Q->data[Q->front];
}
void printQueue(Queue Q){
if(Q->front == Q->rear)
printf("\n");
int front = Q->front;
int rear = Q->rear;
while(front != rear){
printf("%d -> ", Q->data[front + 1]);
front = (front + 1) % MAXSIZE;
}
printf("\n");
}
int main()
{
Queue Q = initialQueue();
addQ(Q, 1);
addQ(Q, 2);
addQ(Q, 3);
printQueue(Q);
deleteQ(Q);
deleteQ(Q);
printQueue(Q);
return 0;
}
队列的链式存储
队列的链式存储不需要实现上述类似的循环队列,因为不存在队列满的情况。
我们同样使用一个带有头指针和尾指针的结构体来实现队列。
我这里实现的头指针是链表的头结点,起到辅助编程的作用,第二个结点存储的元素才是队列的第一个元素。
尾指针则是指向链表最后一个结点的地址。
#include <stdio.h>
#include <stdlib.h>
#define ERROR -1
typedef struct QNode QNode;
struct QNode{
int val;
QNode* next;
};
struct LinkQueue{
QNode *rear; // 队头结点
QNode *front; // 队尾结点
};
typedef struct LinkQueue *Queue;
typedef struct LinkQueue LinkQueue;
Queue initialQueue(){
Queue Q = (Queue)malloc(sizeof(LinkQueue));
Q->rear = NULL;
Q->front = (QNode*)malloc(sizeof(QNode));
Q->front->val=-1; // make no sense.
Q->front->next=Q->rear;
return Q;
}
int AddQ(Queue Q, int val){
QNode* qnode = (QNode*)malloc(sizeof(QNode));
qnode->val = val;
qnode->next=NULL;
if(Q->rear == NULL){
Q->rear = qnode;
Q->front->next=qnode;
}
else{
// printf("%d", Q->front->next->val);
Q->rear->next = qnode;
Q->rear = Q->rear->next;
}
}
int deleteQ(Queue Q){
if(Q->front->next == NULL){
printf("The queue is empty!\n");
return ERROR;
}
int val = 0;
QNode* node = Q->front->next;
val = node->val;
if(node == Q->rear){
// 只剩下一个结点
free(node);
Q->rear = Q->front->next = NULL;
}
else{
Q->front->next = node->next;
free(node);
}
return val;
}
void printQueue(Queue Q){
if(Q->front->next==NULL){
printf("print: queue is empty.\n");
return;
}
QNode* qnode = Q->front->next;
while(qnode){
printf("%d ->", qnode->val);
qnode = qnode->next;
}
printf("\n");
}
int main()
{
Queue Q = initialQueue();
AddQ(Q, 1);
AddQ(Q, 2);
AddQ(Q, 4);
AddQ(Q, 5);
printQueue(Q);
deleteQ(Q);
deleteQ(Q);
printQueue(Q);
return 0;
}
以上代码仅经过简单的测试,如果存在问题,欢迎留言指教,谢谢!