大话数据结构9栈和队列

来源:互联网 发布:软件需求分析案例 编辑:程序博客网 时间:2024/05/27 00:28

1、队列的定义:只允许在一端进行插入操作,而另一端进行删除操作的线性表。例如操作系统和客服系统。

  队列是一种先进先出(First In First Out)的线性表,简称FIFO,允许插入的一端称为队尾,允许删除的一端称为队头。front指针指向队列元素,rear指针指向队尾元素的下一个位置。所以当front等于rear时,代表着一个空队列。

2、队列的抽象数据类型:不同于一般的线性表,插入数据只能在队尾进行,删除数据只能在队头进行。

ADT 队列(Queue)Data同线性表。元素具有相同的类型,相邻元素具有前驱和后继关系。OperationInitQueue(*Q):初始化操作,建立一个空队列Q。DestroyQueue(*Q):若队列Q存在,则销毁它。ClearQueue(*Q):将队列Q清空。QueueEmpty(Q):若队列Q为空,返回true,否则返回false。GetHead(Q,*e):若队列存在且非空,用e返回队列Q的队头元素。EnQueue(*Q,e):若队列Q存在,插入新元素e到队列Q中并成为队尾元素。DeQueue(*Q,*e):删除队列Q中队头元素,并用e返回其值。QueueLength(Q):返回队列Q的元素个数。endADT
3、循环队列

队列顺序存储的不足:

入队列操作是将元素加在队尾,不需要移动任何元素,时间复杂度为O(1)。出队列操作需要队列中的所有元素都向前移动,一保证队列的队头不为空,时间复杂度为O(n)。

循环队列的定义:队列的头尾相接的顺序存储结构

在循环队列中,如何判断队列是空还是满?

  1、设置符号标志量flag,当front == rear且flag = 0时队列为空,当front == rear且flag = 1时,队列为满。

  2、当队列空时,条件就是front = rear,当队列满时,条件改为保留一个元素空间,即(rear + 1) % QueueSize == front,通用的计算队列长度公式:(rear - front + QueueSize) % QueueSize

  循环队列的顺序存储结构代码:

typedef int QElemType;/*QElemType类型根据实际情况而定,这里假设为int*//*循环队列的顺序存储结构*/typedef struct{QelemType data[MAXSIZE];int front;    /*头指针*/int rear;     /*尾指针,若队列不空,指向列尾元素的下一个位置*/}SqQueue;
  循环队列的初始化代码:

/*初始化一个空队列*/

Status InitQueue(SqQueue *Q){Q->front = 0;Q->rear = 0;return OK;}

  循环队列求长度的代码:

/*返回Q的元素个数,即队列的当前长度*/

int QueueLength(SqQueue Q){return (Q.rear - Q.front + MAXSIZE) % MAXSIZE;}
  循环队列的入队列操作代码:

/*若队列未满,则插入元素e为Q新的队尾元素*/

Status EnQueue(SqQueue *Q,QelemType e){if((Q->rear + 1) % MAXSIZE == Q->front)  /*队列满的判断*/return ERROR;Q->data[Q->rear] = e;    /*将元素e赋值给队尾*/Q->rear = (Q->rear + 1) % MAXSIZE;   /*rear指针向后一位置*/    /*若到最后则转到数组头部*/return OK;}

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

/*若队列不空,则删除Q中队头元素,用e返回其值*/Status DeQueue(SqQueue *Q,QElemType *e){if(Q->front == Q->rear)      /*队列空的判断*/return ERROR;*e = Q->data[Q->front];      /*将队头元素赋值给e*/Q->front = (Q->front + 1) % MAXSIZE; /*front指向向后移一位置*/   /*若到最后则转到数组头部*/return OK;}

  循环队列面临着数组溢出的问题,所以就有不用担心队列长度的链式存储结构。

4、队列的链式存储结构及实现

  队列的链式存储结构定义:就是线性表的单链表,只不过只能尾进头出。

  链队列的结构:

typedef int QElemType;  /*QElemType类型根据实际情况而定,这里假设为int*/typedef struct QNode /*结点结构*/{QElemType data;struct QNode *next;}Qnode,*QueuePtr;typedef struct            /*队列的链表结构*/{QueuePtr front,rear;  /*队头、队尾指针*/}LinkQueue;
  队列的链式存储结构的入队操作:

/*插入元素e为Q的新的队尾元素*/Status EnQueue(LinkQueue *Q,QElemType e){QueuePtr s = (QueuePtr)malloc(sizeof(QNode));if(!s)       /*存储分配失败*/exit(OVERFLOW);s->data = e;s->next = NULL;Q->rear->next = s;    /*把拥有元素e新结点s赋值给原队尾结点的后缀*/Q->rear = s;        /*把当前的s设置为队尾结点,rear指向s*/return OK;}

  队列的链式存储结构的出队操作:将头结点的后缀结点出队,再将头结点的后缀改为其后面的结点,若链表除头结点外只剩下一个元素时,则需要将rear指向头结点。

/*若队列不空,删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR*/Status DeQueue(LinkQueue *Q,QELemType *e){QueuePtr p;if(Q->front == Q->rear)return ERROR;p = Q->front->next;  /*将欲删除的队头结点暂存给p*/*e = p->data;      /*将欲删除的队头结点的值赋值给e*/Q->front->next = p->next;  /*将原队头结点后继p->next赋值给头结点后继*/if(Q->rear == p)   /*若队头是队尾,则删除后将rear指向头结点*/Q->rear = Q->front;free(p);return OK;}




 



0 0