数据结构--队列实现(顺序队列和链队列)与C++模板
一、顺序队列
队列的顺序存储结构称为顺序队列,顺序队列实际上是运算受限的顺序表。
①和顺序表一样,顺序队列用一个向量空间来存放当前队列中的元素。
②由于队列的队头和队尾的位置是变化的,设置两个指针front和rear分别指示队头元素和队尾元素在向量空间中的位置,它们的初值在队列初始化时均应置为0。
注意:
①当头尾指针相等时,队列为空。
②在非空队列里,队头指针始终指向队头元素,尾指针始终指向队尾元素的下一位置。(所以以下循环顺序队列中当队尾指针指向了队头指针的前一位就表示队列已经满了)
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define OK 1
#define FAIL 0
//最大队列长度 循环队列的大小减1 为了区分队空与队满的判断
#define QUEUE_MAX_SIZE (10+1)
typedef int QElemType;
//基于数组
typedef struct
{
QElemType *queue;
int front; //表示当前队列的头
int rear; //表示队尾 插入数据的位置(没有数据)
}MY_QUEUE_T;
int my_atoi(char *str, int m)
{
int i;
int num = 0;
if(!str) return FAIL;
while(str[i] != '\0')
{
if(!isdigit(str[i]))
return FAIL;
num = num*10 + str[i] - '0';
i++;
}
return OK;
}
//初始化队列
void Queue_Init(MY_QUEUE_T *q)
{
q->queue = (QElemType *)malloc(QUEUE_MAX_SIZE * sizeof(QElemType));
q->front = 0;
q->rear = 0;
if(!q->queue)
exit(-1);
else
printf("Queue Init OK!\n");
}
//队列空判断
int Queue_Empty(MY_QUEUE_T *q)
{
if(q->front == q->rear)
{
printf("The queue is empty!\n");
return OK;
}
else
return FAIL;
}
//队列满判断
int Queue_Full(MY_QUEUE_T *q)
{
if((q->rear + 1)%QUEUE_MAX_SIZE == q->front)
{
printf("The queue is Full!\n");
return OK;
}
else
return FAIL;
}
//取队头元素 并将队头元素出队
int Queue_Pop(MY_QUEUE_T *q, int *e)
{
if(Queue_Empty(q))
return FAIL;
*e = q->queue[q->front];
q->front = (q->front + 1) % QUEUE_MAX_SIZE;
return OK;
}
//队尾插入元素元素 返回插入是否成功
int Queue_Push(MY_QUEUE_T *q,int <span style="font-family: Arial, Helvetica, sans-serif;">e)</span>
{
if(Queue_Full(q)) //队列满 则返回插入失败
return FAIL;
q->queue[q->rear] = e;
q->rear = (q->rear + 1) % QUEUE_MAX_SIZE;
printf("Insert %d at the queue position %d!\n",e,q->rear);
return OK;
}
//打印队列元素
void Queue_Print(MY_QUEUE_T *q)
{
int i;
if(!Queue_Empty(q))
{
printf("The queue is:");
for(i=q->front; i!=q->rear; i++)
{
printf(" %d",q->queue[i]);
if((i+1) % QUEUE_MAX_SIZE == 0)
i = -1; //for 循环自动+1
}
printf("\n");
}
}
int main(int argc, char **argv)
{
MY_QUEUE_T my_queue;
char *str;
int num;
Queue_Init(&my_queue);
printf("Please input action,'P' or 'q'\n");
while(scanf("%s",str)!=EOF)
{
if(*(str) == 'p' || *(str) == 'P')
{
printf("Please input insert num:");
scanf("%d",&num);
if(!Queue_Push(&my_queue,num))
{
printf("Queue Push Fail!\n");
}
}
else if(*(str) == 'q' || *(str) == 'Q')
{
if(Queue_Pop(&my_queue, &num))
{
printf("Get the queue head :%d\n",num);
}
}
Queue_Print(&my_queue);
printf("Please input action,'P' or 'q'\n");
}
return 0;
}
队列的链式存储结构简称为链队列。它是限制仅在表头删除和表尾插入的单链表。
注意:
增加指向链表上的最后一个结点的尾指针,便于在表尾做插入操作。
链队列示意图见上图,图中Q为ListNode型的指针。
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define OK 1
#define FAIL 0
//用链表队列长度无限制
typedef int QElemType;
//定义链表
typedef struct ListNode
{
QElemType data;
struct ListNode *next;
}ListNode;
typedef ListNode *PtrList;
ListNode Head;
//基于链表的队列模型
typedef struct
{
PtrList front;
PtrList rear;
}MY_QUEUE_T;
//初始化队列
void Queue_Init(MY_QUEUE_T *q)
{
q->front = q->rear = (PtrList)malloc(sizeof(ListNode));
q->front->next = NULL;
if(!q->front)
exit(-1);
else
printf("Queue Init OK!\n");
}
//队列空判断
int Queue_Empty(MY_QUEUE_T *q)
{
if(q->front == q->rear)
{
printf("The queue is empty!\n");
return OK;
}
else
return FAIL;
}
//取队头元素 并将队头元素出队
int Queue_Pop(MY_QUEUE_T *q, QElemType *e)
{
PtrList p;
if(Queue_Empty(q))
return FAIL;
p = q->front; //获取队列头结点 p用于释放出队后的结点空间
*e = p->data; //获取头结点数据
q->front = p->next; //移动队列头指针到下一个结点
free(p);
return OK;
}
//队尾插入元素元素 返回插入是否成功
int Queue_Push(MY_QUEUE_T *q, QElemType e)
{
PtrList new_node = (PtrList)malloc(sizeof(ListNode));
new_node->next = NULL;
if(!new_node) return FAIL; //申请内存失败 插入不成功
q->rear->data = e; //插入数据到当前结点
q->rear->next = new_node; //当前结点next指向新申请的结点
q->rear = new_node; //队列尾指针指向新申请的结点
printf("Insert %d at the queue!\n",e);
return OK;
}
//打印队列元素
void Queue_Print(MY_QUEUE_T *q)
{
PtrList p;
p = q->front;
if(!Queue_Empty(q))
{
printf("The queue is:");
while(p != q->rear)
{
printf(" %d",p->data);
p = p->next;
}
printf("\n");
}
}
int main(int argc, char **argv)
{
MY_QUEUE_T my_queue;
char *str;
int num;
Queue_Init(&my_queue);
printf("Please input action,'P' or 'q'\n");
while(scanf("%s",str)!=EOF)
{
if(*(str) == 'p' || *(str) == 'P')
{
printf("Please input insert num:");
scanf("%d",&num);
if(!Queue_Push(&my_queue,num))
{
printf("Queue Push Fail!\n");
}
}
else if(*(str) == 'q' || *(str) == 'Q')
{
if(Queue_Pop(&my_queue, &num))
{
printf("Get the queue head :%d\n",num);
}
}
Queue_Print(&my_queue);
printf("Please input action,'P' or 'q'\n");
}
return 0;
}
三、C++队列模板
头文件 #include <queue>