第二讲线性结构
2.3队列
队列的基础知识
队列:具有一定操作约束的线性表
- 特点:
- 插入和删除操作:只能在一端插入,而在另一端删除
数据插入:入队列
数据删除:出队列- 先进先出
数据对象集:一个有0个或多个元素的有穷线性表
操作集:长度为MaxSize的堆栈S∈Stack,堆栈元素item∈ElementType
1.Queue CreateQueue(int MaxSize):生成长度为MaxSize的空队列
2.int IsFullQ(Queue Q, int MaxSize):判断队列Q是否为空
3.void AddQ(Queue Q, ElementType item):将数据元素item插入队列Q中
4.int IsEmptyQ(Queue Q):判断队列Q是否为空
5.ElementType DeleteQ(Queue Q):将对头数据元素从队列中删除并返回
队列的顺序存储实现
队列的顺序存储结构通常由一个一维数组和一个记录队列头元素位置的变量front以及一个记录队列尾元素位置的变量rear组成
- 使用一个结构来表示队列
每增加一个元素,rear的值+1,每删除一个元素,front的值+1。
#define MaxSize<储存数据元素的最大个数>
struct QNode{
ElementType Data[MaxSize];
int rear;
int front;
};
typedef struct QNode *Queue;
每增加一个元素,rear的值+1,每删除一个元素,front的值+1。删除元素后,数组前面便空出了位置,没法充分利用空间,于是就有了循环队列
- (实现循环队列的方法是使用求余函数)
但是循环队列存在一个问题当front=rear时,到底是队列满了还是为空
解决方法:
- 1.使用额外标记:Size(用来记录当前对列的个数)或tag(最后一次操作为:0/1)域
- 2.仅使用n-1个数组空间
此处采用第二种方法:即存放n-1个元素
- 入队列
void AddQ(Queue PtrQ,ElementType item)
{
if(PtrQ->rear+1)%MaxSize==PtrQ->front{
printf("队列满");
return;
}
PtrL->rear=(PtrQ->rear+1)%MaxSize;
PtrQ->Data[PtrQ->rear]=item;
}
- 出队列
ElementType DeleteQ(Queue PtrQ)
{
if(PtrQ->front==PtrQ->rear){
printf("队列空");
return ERROR;
}else{
PtrQ->front=(PtrQ->front+1)%MaxSize;
return PtrQ->Data[PtrQ->front];
}
}
队列的链式存储实现
队列的链式存储结构也可以用一个的单链表实现。插入和删除操作分别在链表的两头进行
- 队列的结构
struct Node{
ElementType Data;
struct Node *Next;
};
struct QNode{ //链队列结构
struct Node *rear; //指向队尾节点
struct Node *front; //指向队头节点
};
typedef struct QNode *Queue;
Queue PtrQ;
- 不带头结点的链式队列出队
ElementType DeleteQ(Queue PtrQ)
{
struct Node *Front Cell;
ElementType FrontElem;
if(PtrQ->front==NULL){
printf("队列空");
return ERROR;
}
FrontCell=PtrQ->front; //找到队列的头元素
if(PtrQ->front==PtrQ->rear){ //若队列只有一个元素
PtrQ->front=PtrQ->rear=NULL; //删除后队列后置为空
}else{
PtrQ->front=PtrQ->front->Next;
FrontElem=FrontCell->Data;
free(FrontCell); //释放被删除节点空间
return Front Elem;
}
}
- 不带头结点链式队列入队
待补充