3.2 队列

一、队列的概念
1.队列,一种操作受限的线性表,只允许在一端插入,在另一端删除。其操作特性是先进先出。
队头。允许删除的一端。
队尾。允许插入的一端。
空队列。不含任何元素的空表。

2.队列常见的基本操作。
InitQueqe(&Q):初始化队列,构造一个空队列Q
QueueEmpty(Q):判队列空,若队列Q为空则返回true,否则返回false
EnQueue(&Q,x):入队,若队列Q未满,将x加入,使之成为新的队尾
DeQueue(&Q,&x):出队,若队列Q非空,删除队头元素,并用x返回
GetHead(Q,&x):读对头元素,若队列Q非空,则将队头元素赋值给x

二、队列的顺序存储结构
1.队列的顺序存储
	队列的顺序实现是指分配一块连续的存储单元存放队列中的元素,并附设两个指针:队头指
针front指向队头元素,队尾指针rear指向队尾元素的下一个位置。
	队列的顺序存储类型可描述为
	#define MaxSize 50							//定义队列中元素的最大个数
	typedef struct{
    
    
	ElemType data[MaxSize];						//存放队列元素
	int front,rear;								//队头指针和队尾指针
	}SqQueue;
	初始状态(队空条件):Q.front==Q.rear==0
	进队操作:队不满时,先送值到队尾元素,再将队尾指针+1
	出队操作:队不空时,先取队头元素值,再将队头指针+1

2.循环队列
	将顺序队列臆造为一个环状的空间,称为循环队列。当队首指针Q.front=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.rear+1)%MaxSize==Q.front
	队空条件:Q.front==Q.rear
	队列中元素的个数:(Q.rear+MaxSize-Q.front)%MaxSize

	(2)类型中增设表示元素个数的数据成员。这样,队空的条件为Q.size==0;队满的条件为
Q.size==MaxSize.

	(3)类型中增设tag数据成员。tag=0时,若因删除导致Q.front==Q.rear,则为队空;
tag=1时,若因插入导致Q.front==Q.rear则为队满。

3.循环队列的操作
(1)初始化
	void InitQueue(SqQueue &Q){
    
    
		Q.front=Q.rear=0;			//初始化队首、队尾指针
	}

(2)判队空
	bool isEmpty(SqQueue Q){
    
    
		if(Q.front==Q.rear)
			return true;
		else
			return false;
	}

(3)入队
	bool EnQueue(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;
	}

(4)出队
	bool 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;
	}

三、队列的链式存储结构
1.队列的链式存储
	队列的链式表示称为链队列,它实际上是一个同时带有队头指针和队尾指针的单链表。头指
针指向队头结点,尾指针指向队尾结点,即单链表的最后一个结点。
	队列的链式存储类型可描述为
	typedef struct{
    
    					//链式队列结点
		ElemType data;
		struct LinkNode *next;
	}LinkNode;
	typedef struct{
    
    					//链式队列
		LinkNode *front,*rear;		//队列的队头和队尾指针
	}LinkQueue;
	当Q.front==NULL且Q.rear==NULL时,链式队列为空。

2.链式队列的基本操作
(1)初始化
	void InitQueue(LinkQueue &Q){
    
    
		Q.front=Q.rear=(LinkNode*)malloc(sizeof(LinkNode));//建立头结点
		Q.front->next=NULL;		//初始为空
	}

(2)判队空
	bool IsEmpty(LinkQueue Q){
    
    
		if(Q.front==Q.rear)
			return true;
		else
			return false;
	}

(3)入队
	void EnQueue(LinkQueue &Q,ElemType x){
    
    
		LinkNode *s=(LinkNode *)malloc(sizeof(LinkNode));
		s->data=x;
		s->next=NULL;	//创建新结点,插入到链尾
		Q.rear->next=s;
		Q.rear=s;
	}

(4)出队
	bool DeQueue(LinkQueue &Q,ElemType &x){
    
    
		if(Q.front==Q.rear)
			return false;//空队
		LinkNode *p=Q.front->next;
		x=p->data;
		Q.front->next=p->next;
		if(Q.rear==p)
			Q.rear=Q.front;//若原队列中只有一个结点,删除后变空
		free(p);
		return true;
	}

四、双端队列
	双端队列是指允许两端都可以进行入队和出队操作的队列。
	输出受限的双端队列:允许在一端进行插入和删除,但在另一端只允许插入
	输入受限的双端队列:允许在一端进行插入和删除,但在另一端只允许删除

猜你喜欢

转载自blog.csdn.net/SeNiLS/article/details/114522683
3.2