队列
队列(Queue):是运算受限的线性表。是一种先进先出(First In First Out ,简称FIFO)的线性表。只允许在表的一端进行插入,而在另一端进行删除。
队首(front) :允许进行删除的一端称为队首。
队尾(rear) :允许进行插入的一端称为队尾。
一 队列的静态顺序存储
#define MAX_QUEUE_SIZE 100
typedef struct queue{
ElemType Queue_array[MAX_QUEUE_SIZE] ;
int front ;
int rear ;
}SqQueue;
顺序队列中存在“假溢出”现象。因为在入队和出队操作中,头、尾指针只增加不减小,致使被删除元素的空间永远无法重新利用。因此,尽管队列中实际元素个数可能远远小于数组大小,但可能由于尾指针巳超出向量空间的上界而不能做入队操作。该现象称为假溢出。
1.1 循环队列
为充分利用向量空间,克服上述“假溢出”现象的方法是:将为队列分配的向量空间看成为一个首尾相接的圆环,并称这种队列为循环队列(Circular Queue)。
- 循环队列为空:front=rear;
- 循环队列满:(rear+1)%MAX_QUEUE_SIZE =front;
1.1.1 循环队列的初始化
SqQueue Init_CirQueue(void)
{
SqQueue Q;
Q.front = Q.rear = 0;
return Q;
}
1.1.2 入队操作
/* 将数据元素e插入到循环队列Q的队尾 */
Status Insert_CirQueue(SqQueue Q, ElemType e)
{
if((Q.rear+1)%MAX_QUEUE_SIZE== Q.front)
return ERROR; //队满,返回错误标志
Q.Queue_array[Q.rear]=e; //元素e入队
Q.rear=(Q.rear+1)% MAX_QUEUE_SIZE; //队尾指针向前移动
return OK; //入队成功
}
1.1.3 出队操作
/*将循环队列Q的队首元素出队*/
Status Delete_CirQueue(SqQueue Q, ElemType *x )
{
if(Q.front == Q.rear)
return ERROR ; //队空,返回错误标志
*x=Q.Queue_array[Q.front] ; //取队首元素
Q.front=(Q.front+1)% MAX_QUEUE_SIZE ; //队首指针向前移动
return OK ;
}
二 队列的链式存储
数据元素结点:
typedef struct Qnode{
ElemType data;
struct Qnode *next;
}QNode;
指针结点类型:
typedef struct link_queue
{
QNode *front, *rear;
}Link_Queue;
2.1 链队列的初始化
LinkQueue *Init_LinkQueue(void)
{
LinkQueue *Q;
QNode *p;
p=(QNode *)malloc(sizeof(QNode)); //开辟头结点
p->next=NULL;
Q=(LinkQueue *)malloc(sizeof(LinkQueue)); //开辟链队的指针结点
Q.front = Q.rear = p;
return Q;
}
2.2 链队列的入队操作
/* 将数据元素e插入到链队列Q的队尾 */
Status Insert_CirQueue(LinkQueue *Q, ElemType e)
{
p=(QNode *)malloc(sizeof(QNode));
if (!p)
return ERROR; //申请新结点失败,返回错误标志
p->data=e;
p->next=NULL; //形成新结点
Q.rear->next=p ;
Q.rear=p ; //新结点插入到队尾
return OK;
}
2.3 链队列的出队操作
Status Delete_LinkQueue(LinkQueue *Q, ElemType *x)
{
QNode *p ;
if(Q.front==Q.rear)
return ERROR; //队空
p=Q.front->next ; //取队首结点
*x=p->data ;
Q.front->next = p->next ; //修改队首指针
if(p==Q.rear)
Q.rear=Q.front; //当队列只有一个结点时应防止丢失队尾指针
free(p);
return OK;
}
2.4 链队列的撤消
/* 将链队列Q的队首元素出队 */
void Destroy_LinkQueue(LinkQueue *Q )
{
while(Q.front!=NULL)
{
Q.rear = Q.front->next; //令尾指针指向队列的第一个结点
free(Q.front); //每次释放一个结点
//第一次是头结点,以后是元素结点 */
Q.front = Q.rear;
}
}