数据结构之线性结构(队列)

本文为数据结构之线性结构(队列),根据网课而整合的笔记。

什么是队列

队列(Queue):具有一定操作约束的线性表

插入和删除操作:只能在一端插入,而在另一端删除。

  • 数据插入:入队列(AddQ)
  • 数据删除:出队列(DeleteQ)
  • 先来先服务
  • 先进先出:FIFO

队列的抽象数据类型描述

类型名称:队列(Queue)

数据对象集:一个有0个或多个元素的有穷线性表。

操作集:长度为Maxsize的队列Q《Queue,队列元素item《ElementType

1.Queue CreatQueue(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(指向队列头元素的前一个,若无删除时为-1)以及一个记录队列尾元素位置的变量rear组成。(当front===rear时,队列为空)

#define MaxSize<储存数据元素的最大个数>
struct 	QNode{
    
    
	ElementType Data[MaxSize];
	int rear;
	int front;
};
typedef struct QNode*Queue;

【例】一个工作队列

在这里插入图片描述
在这里插入图片描述
思考:

(1)这种方案:堆栈空和满的判别条件是什么?

解决方案:

  • 使用额外标记:Size(元素个数,加入一个元素时+1,删除一个元素时-1,根据Size为0或1来判断是空或满)或者tag(插入一个元素时tag为1,删除一个元素时tag为0,根据tag为0或1来判断最后一次操作,从而判断是空或满)域
  • 仅使用n-1个数组空间

(2)为什么会出现空、满无法区分?根本原因?

根据front与rear的差距判断,如上图差距有6种情况:0,1,2,3,4,5

而上图的队列装载元素个数情况有7种:0(空队列),1(一个元素),2,3,4,5,6

所以队列的差距情况有n种而队列装载元素个数情况有n+1种,必有矛盾。

(1)入队列

void AddQ(Queue PtrQ,ElementType item)
{
    
    
	if((PtrQ->rear+1)%MaxSize == PtrQ->front){
    
    
		printf("队列满")return;
	}
	PtrQ->rear = (PtrQ->rear+1)%MaxSize;
	PtrQ->Data[PtrQ->rear]=item;
}

(2)出队列

ElementType DeleteQ(Queue PtrQ)
{
    
    
	if(PtrQ->front == PtrQ->rear){
    
    
		printf("队列空")return ERROR;
	}else{
    
    
		PtrQ->front = (PtrQ->front+1)%MaxSize;
		return PtrQ->Data[PtrQ->front];
	}
}

Front和rear指针的移动采用“加1取余”法,体现了顺序存储的“循环使用”。

队列的链式存储实现

队列的链式存储结构也可以用一个单链表实现。插入和删除操作分别在链表的两头进行

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 *FrontCell;
	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 FrontElem;
}

声明:部分资料源自网络,如有侵权,请联系我删除!
文中如存在谬误、混淆等不足,欢迎批评指正!

猜你喜欢

转载自blog.csdn.net/hxtxsdcxy/article/details/113796815