[关闭]
@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

有了以上的铺垫,再实现循环队列的代码就不难了
约定:头指针指向队头元素,尾指针指向队尾元素的下一位
循环队列的结构如下:

  1. typedef struct
  2. {
  3. int data[MAXSIZE];
  4. int front;/*头指针*/
  5. int rear;/*尾指针,若队列不空,指向队列尾元素的下一个位置*/
  6. }SqQueue
  1. /*循环队列的初始代码*/
  2. int InitQueue(SqQueue *Q)
  3. {
  4. Q->front = 0;
  5. Q->rear =0;
  6. return TRUE;
  7. }

循环队列求队列长度:

  1. /*返回Q的元素个数,也就是队列的当前长度*/
  2. int QueueLength(SqQueue Q)
  3. {
  4. return(Q.rear-Q.front+MAXSIZE)%MAXSIZE;
  5. }

循环队列的入队操作代码:

  1. /*若队未满,则插入元素e为Q新的队尾元素*/
  2. int InQueue(SqQueue *Q, int x)
  3. {
  4. if(Q->rear+1)%MAXSIZE == Q->front) /*队满判断*/
  5. return FALSE;
  6. Q->data[Q->rear]=x;/*将元素x赋值给对尾*/
  7. Q->rear = (Q->rear+1)%MAXSIZE;/*rear指针向后移一位,若到最后则指到数组头部*/
  8. return TRUE;
  9. }

循环队列的出队

  1. /*若队列不空,则删除Q中元素队头元素,用e返回其值*/
  2. int DeleQueue(Squeue *Q, int *x)
  3. {
  4. if(Q->front == Q->rear)/*队空的判断*/
  5. return FALSE
  6. *x=Q->data[Q->front];
  7. Q->front = (Q->front+1)%MAXSIZE;
  8. return TRUE;
  9. }

从前边我们可以了解到 单是顺序存储,若不是循环队列,算法的时间性能是不高的,但循环队列又面临着数组可能会溢出的问题,所以我们接下来研究一下不需要担心长度的链式存储结构。
队列的链式存储结构,其实就是线性表的单链表,只不过他只能尾进头出而已。我们称之为链队列。

为了操作方便,我们将队头指针指向链队列的头节点,而队尾指向终端节点。(队列7)
当空队时front和head都指向头结点(队列8)

链式队列的存储结构
通常将队头指针和队尾指针封装在一个结构体中,并将该结构体类型重新命名为链队列类型

  1. typedef struct QNode /*节点结构*/
  2. {
  3. int data
  4. struct QNode *next;
  5. }QNode,*Queueptr;
  6. typedef struct /*队列的链表结构*/
  7. {
  8. QNode * front;
  9. QNode * rear;
  10. (结构体中有两个指针,指针的结构体类型与结点相同)
  11. }LinkQueue

链队列初始化
就是在链表尾部插入节点(队列9)

  1. int InitQueue(LinkQueue *Q)
  2. {/*将Q初始化为一个空的链队列*/
  3. Q->front = (QNode *)malloc(sizeof(QNode));/*为了初始化链队列头节点*/
  4. if(Q->front != NULL)
  5. {
  6. Q->rear = Q->front;
  7. Q->front->next = NULL;
  8. return TRUE;
  9. }
  10. else
  11. return FALSE;/*溢出!*/
  12. }

链队列入队操作就是在链表尾部插入节点

  1. /*插入元素x为Q的新队尾元素*/
  2. int InQueue (QNode *Q, int e)
  3. {
  4. LNode *s = (LNode*)malloc(sizeof(LNode));
  5. if(s != NULL)
  6. {
  7. s->data = x;
  8. s->next = NULL;
  9. Q->rear->next = s;
  10. Q->rear = s;
  11. return (TRUE);
  12. }
  13. else
  14. return FALSE;/*存储分配失败*/
  15. }

lan

  1. typedef struct
  2. {
  3. char name[20];
  4. char sex;
  5. }Person;
  6. typedef Person DataType; /*将队列中元素数据类型改为person*/
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注