队列
一种操作受限的线性表,只允许在表的一端插入,而在表的另一端删除,特性:先进先出
队头:允许删除的一端,又称队首。
队尾:允许插入的一端.
1.顺序存储结构:
重点看循环队列:为了解决假溢出现象并使队列得到充分利用,将顺序队列想象成一个环状的空间,即把存储队列元素的表从逻辑上视为一个环,称为循环队列。
在非空循环队列中,队头指针始终指向当前的队头元素,而队尾指针始终指向真正队尾元素后面的单元
当队首指针Q.font=Q.MaxSize-1后,再前进一个位置就自动到0,这就可以利用除法取余运算来实现。
初始时:Q.front=Q.rear=0
队首指针进1:Q.front=(Q.front+1)%MaxSize
队尾指针进1:Q.rear=(Q.rear+1)%MaxSize
队列长度:(Q.rear+MaxSize-Q.front)%MaxSize
出队入队时:指针都顺时针方向进1
判队空:Q.front=Q.rear
判队满:
1.损失一个元素空间,当队尾指针所指向的空单元的后继单元是队头元素所在的单元
时,则停止入队。队满:(Q.rear+1)%MaxSize等于等于Q.front
2.增设表示元素个数的数据单元,队空:Q.size=0;队满:Q.size=MaxSize
3.增设tag数据成员,初始化时:rear=front=tag=0;每次删除成功:tag=0;每次插入成功:tag=1;
队满:front等于等于rear&&tag等于等于1 队空:front==rear&&tag=0,删除才可能致空,插入才可能致满。
(1)
#include "stdio.h"
#include "stdlib.h"
typedef int ElemType;
#define MaxSize 50
#define true 1
#define false 0
typedef struct {
ElemType data[MaxSize];//存放队列元素
int front, rear;//队头指针和队尾指针
}SqQueue;
//初始化
void InitQueue(SqQueue* Q) {
Q->rear = Q->front = 0;
}
//判断空
int IsEmpty(SqQueue Q) {
if (Q.rear == Q.front)
return true;
else
return false;
}
//入队
int EnterQueue(SqQueue *Q, ElemType x) {
if ((Q->rear + 1) % MaxSize == Q->front)//队满则报错
return false;
Q->data[Q->rear] = x;
Q->rear = (Q->rear + 1) % MaxSize;//队尾指针加1取模
return true;
}
//出队
int DeQueue(SqQueue* Q, ElemType* x) {
if (Q->rear == Q->front)//队空则报错
return false;
x = Q->data[Q->front];
Q->front = (Q->front + 1) % MaxSize;//队头指针加1取模
return true;
}
(2)
typedef struct {
ElemType data[MaxSize];
int front, rear;
int tag;
}SeqQueue;
void InitQueueC(SeqQueue* Q) {
Q->rear = Q->front = 0;
Q->tag = 0;
}
int Isempty(SeqQueue Q) {
if (Q.front == Q.rear && Q.tag == 0)
return true;
else
return false;
}
int enterQueue(SeqQueue* Q, ElemType x) {
if (Q->front == Q->rear && Q->tag == 1)
return false;
Q->data[Q->rear] = x;
Q->rear = (Q->rear + 1) % MaxSize;
Q->tag = 1;
return true;
}
int Dequeue(SeqQueue* Q, ElemType* x) {
if (Q->front == Q->rear && Q->tag == 0)
return false;
*x = Q->data[Q->front];
Q->front = (Q->front + 1) % MaxSize;
Q->tag = 0;
return true;
}
(3)
typedef struct {
ElemType data[MaxSize];
int front, rear;
int size;
}Queue;
void init(Queue* Q) {
Q->rear = Q->front = 0;
Q->size = 0;
}
int isEmpty(Queue Q) {
if (Q.size == 0)
return true;
else
return false;
}
int enqueue(Queue* Q, ElemType x) {
if (Q->size == MaxSize)
return false;
Q->data[Q->rear] = x;
Q->rear = (Q->rear + 1) % MaxSize;
Q->size++;
return true;
}
int dequeue(Queue* Q, ElemType* x) {
if (Q->size == 0)
return false;
*x = Q->data[Q->front];
Q->front = (Q->front + 1) % MaxSize;
Q->size--;
return true;
}
2.链队列
若采用带头结点的链表结构:队头指针始终指向头结点,队尾指针指向最后一个元素,空的链队列的队头指针和队尾指针均指向头结点。
typedef struct Node{//链式队列结点
ElemType data;
struct Node *next;
}LinkQueueNode;
typedef struct{//链式队列
LinkQueueNode *front, * rear;//队列的队头和队尾指针
}LinkQueue;
int Initqueue(LinkQueue* Q) {
Q->front = (LinkQueueNode*)malloc(sizeof(LinkQueueNode));
if (Q->front != NULL) {
Q->rear = Q->front;
Q->front->next = NULL;
return true;
}
else
return false;
}
//链队列入队
int EnterLinkQueue(LinkQueue *Q, ElemType x) {
LinkQueueNode *NewNode;
NewNode = (LinkQueueNode*)malloc(sizeof(LinkQueueNode));
if (NewNode != NULL) {
NewNode->data = x;
NewNode->next = NULL;
Q->rear->next = NewNode;
Q->rear = NewNode;
return true;
}
else
return false;
}
//链队列出队
int DeleteQueue(LinkQueue* Q, ElemType* x) {
LinkQueueNode* p;
if (Q->front == Q->rear)
return false;
p = Q->front->next;
Q->front->next = p->next;//队头元素p出队
if (Q->rear == p)//若队中只有一个元素p,则p出队后为空队列
Q->rear = Q->front;
*x = p->data;
free(p);
return true;
}