#include<stdio.h>
#define MaxSize 100
#define OK 1
#define ERROR 0
typedef int Status;//表示返回的状态值
typedef int ElemType;
/*
1、队列可分为“循环队列”和“栈队列”
循环队列 :通过将顺序的内存地址看做首位相连的地址,来实现队列的增删,缺点是队列有最大的固定大小
栈队列 :则是通过链表来实现,更为灵活
2、队列是FIFO(FIRST IN FIRST OUT)机制,
3、还有“双端队列”,即两端都可以增删,可以实现队列和堆栈的功能,但并不常用
*/
//链队列数据结点的结构体定义
typedef struct Node
{
ElemType data;
struct Node *next;
}Node;
//链队列的类型定义
typedef struct
{
Node *front;//存队列头指针,指向头结点,头结点一般不存储数据!!
Node *rear;//存队列尾指针
int length;//队列长度
}Queue;
//初始化队列
//O(1)
Status InitialQueue(Queue &Q)
{
Q.rear=Q.front=(Node*)malloc(sizeof(Node));//为头结点分配一个内存
if(!Q.front)
{
exit(OVERFLOW);
}
Q.front->next=NULL;//为了最后的结点指针指向空
Q.length=0;//初始长度
return OK;
}
//摧毁队列(即将队列的结点以及头结点的内存释放,而Clear不释放头结点)
//O(1)
Status DestroyQueue(Queue &Q)
{
while(!Q.front)//若为NULL则退出
{
Q.rear=Q.front->next;//用rear作为移动指针
free(Q.front);//从头结点开始释放内存
Q.front=Q.rear;//或取下一个结点
}
return OK;
}
//进队
//O(1)
Status EnQueue(Queue &Q,ElemType e)
{
Node *p=(Node*)malloc(sizeof(Node));
if(!p)
{
exit(OVERFLOW);
}
Q.rear->next=p;
Q.rear=p;
Q.rear->data=e;//赋值给新结点
Q.rear->next=Null;//指空表示队尾
return OK;
}
//出队
//O(1)
Status DeQueue(Queue &Q,ElemType &e)
{
Node *p=Q.front->next;//p为要删去的结点
if(Q.front==Q.rear)
{
return ERROR;//空队列不可出队
}
Q.front->next=p->next;//重指向队头
e=p->data;
if(Q.rear==p)
{
Q.rear=Q.front;//此时应该都为NULL
}
free(p);
return OK;
}
//--------------------------------------------------------------------
//循环队列的结构体定义
//通过数组(顺序存储结构)实现
//循环队列中rear应该走在front前面,因为rear是添加数据,因此向前增长
//!!该例中需空出一个数据内存空间用于判别队列是空还是满(即满的时候rear和front不重合)
//!!!!通过%Q.size实现指针的“循环”
typedef struct
{
ElemType *base;//申请内存
int rear;
int front;
int size;//队列最大容量(本设计中不可改变)
}Queue;
//初始化循环队列
//O(1)
Status InitialQueue(Queue &Q)
{
Q.size=MAXSIZE;
Q.base=(ElemType *)malloc(Q.size*sizeof(ElemType));
if(!Q.base)
{
exit(OVERFLOW);
}
Q.front=0;
Q.rear=0;
return OK;
}
//获取队列长度
//O(1)
int GetLength(Queue &Q)
{
if(Q.rear>=Q.front)
{
return (Q.rear-Q.front);
}
else
{
return (Q.size-(Q.front-Q.rear));
}
//也可以用 return (Q.size+Q.rear-Q.front)%Q.size; 直接代替
}
//进队
//O(1)
Status EnQueue(Queue &Q,ElemType e)
{
if(GetLength(Q)==Q.size-1)//或者 Q.front==(Q.rear+1)%Q.size;
{
return ERROR; //表明队列已满,不能进队
}
Q.base[Q.rear]=e;//添加数据
if(Q.rear==Q.size-1)
{
Q.rear=0;
}
else
{
Q.rear++;
}
//上面可改为 Q.rear=(Q.rear+1)%Q.size;
return OK;
}
//出队,并将数据传到e
//O(1)
Status DeQueue(Queue &Q,ElemType &e)
{
if(Q.front==Q.rear)//如果队为空
{
return ERROR;
}
e=Q.base[Q.front]//返回值,同时没有必要对出队的数据进行清零,不是指针没有必要
Q.front=(Q.front+1)%Q.size;//指针向前走一步
return OK;
}