@okokme
2019-01-08T10:29:31.000000Z
字数 2116
阅读 471
数据结构
假设队列数组为Queue[maxsize],当rear+1 == MAXSIZE时,令rear=0.
即rear = (rear + 1)mod MAXSIZE
可以求到Queue[MAXSIZE-1]的后继
而出队对头指针 front = (front+1)modMAXSIZE
此时又出现问题队空时front == rear, 队满时front也等于rear。那么如何判断空满呢?
方法一:设置标志变量flag,flag=0时为空
方法二:修改条件,保留一个元素空间。当front == rear时,只为队空条件。
当rear的下一个元素就是front时,就为队满(队列6)
(但是不能单纯在rear加1,如上图第一个图)
所以此处要用到取模。
(rear + 1) % Maxsize == front
由于front与rear有两种分布方式,即rear在front的左边或rear在front的右边。
当rear > front时,
此时队列的长度为rear-front
当rear < front时
此时队列长度分成两段,一段是Maxsize-front,另一段是0+rear。
加在一起就是 rear-front+MAXSIZE
因此通用公式是(rear-front+MAXSIZE)%MAXSIZE
有了以上的铺垫,再实现循环队列的代码就不难了
约定:头指针指向队头元素,尾指针指向队尾元素的下一位
循环队列的结构如下:
typedef struct
{
int data[MAXSIZE];
int front;/*头指针*/
int rear;/*尾指针,若队列不空,指向队列尾元素的下一个位置*/
}SqQueue;
/*循环队列的初始代码*/
int InitQueue(SqQueue *Q)
{
Q->front = 0;
Q->rear =0;
return TRUE;
}
循环队列求队列长度:
/*返回Q的元素个数,也就是队列的当前长度*/
int QueueLength(SqQueue Q)
{
return(Q.rear-Q.front+MAXSIZE)%MAXSIZE;
}
循环队列的入队操作代码:
/*若队未满,则插入元素e为Q新的队尾元素*/
int InQueue(SqQueue *Q, int x)
{
if(Q->rear+1)%MAXSIZE == Q->front) /*队满判断*/
return FALSE;
Q->data[Q->rear]=x;/*将元素x赋值给对尾*/
Q->rear = (Q->rear+1)%MAXSIZE;/*rear指针向后移一位,若到最后则指到数组头部*/
return TRUE;
}
循环队列的出队
/*若队列不空,则删除Q中元素队头元素,用e返回其值*/
int DeleQueue(Squeue *Q, int *x)
{
if(Q->front == Q->rear)/*队空的判断*/
return FALSE;
*x=Q->data[Q->front];
Q->front = (Q->front+1)%MAXSIZE;
return TRUE;
}
从前边我们可以了解到 单是顺序存储,若不是循环队列,算法的时间性能是不高的,但循环队列又面临着数组可能会溢出的问题,所以我们接下来研究一下不需要担心长度的链式存储结构。
队列的链式存储结构,其实就是线性表的单链表,只不过他只能尾进头出而已。我们称之为链队列。
为了操作方便,我们将队头指针指向链队列的头节点,而队尾指向终端节点。(队列7)
当空队时front和head都指向头结点(队列8)
链式队列的存储结构
通常将队头指针和队尾指针封装在一个结构体中,并将该结构体类型重新命名为链队列类型
typedef struct QNode /*节点结构*/
{
int data;
struct QNode *next;
}QNode,*Queueptr;
typedef struct /*队列的链表结构*/
{
QNode * front;
QNode * rear;
(结构体中有两个指针,指针的结构体类型与结点相同)
}LinkQueue;
链队列初始化
就是在链表尾部插入节点(队列9)
int InitQueue(LinkQueue *Q)
{/*将Q初始化为一个空的链队列*/
Q->front = (QNode *)malloc(sizeof(QNode));/*为了初始化链队列头节点*/
if(Q->front != NULL)
{
Q->rear = Q->front;
Q->front->next = NULL;
return TRUE;
}
else
return FALSE;/*溢出!*/
}
链队列入队操作就是在链表尾部插入节点
/*插入元素x为Q的新队尾元素*/
int InQueue (QNode *Q, int e)
{
LNode *s = (LNode*)malloc(sizeof(LNode));
if(s != NULL)
{
s->data = x;
s->next = NULL;
Q->rear->next = s;
Q->rear = s;
return (TRUE);
}
else
return FALSE;/*存储分配失败*/
}
lan
typedef struct
{
char name[20];
char sex;
}Person;
typedef Person DataType; /*将队列中元素数据类型改为person*/