C语言数据结构——队列

Posted 江州益彤

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言数据结构——队列相关的知识,希望对你有一定的参考价值。

一、队列的基本概念

(1)定义:只能在表的一端进行插入操作,在表的另一端进行删除操作的线性表。
(2)特点:先进先出

示意图如下:
在这里插入图片描述

二、顺序存储结构的队列

有6个存储空间的顺序队列动态示意图
在这里插入图片描述

2.1、顺序队列的“假溢出”问题

①假溢出
顺序队列因多次入队列和出队列操作后出现的虽有存储空间但不能进行入队列操作的情况。

②如何解决顺序队列的假溢出问题?
可采取四种方法:
1 )采用循环队列;
2 )按最大可能的进队操作次数设置顺序队列的最大元素个数;
3 )修改出队算法,使每次出队列后都把队列中剩余数据元素向队头方向移动一个位置;
4)修改入队算法,增加判断条件,当假溢出时,把队列中的数据元素向对头移动,然后方完成入队操作。
在这里插入图片描述

三、顺序循环队列的表示和实现

3.1、顺序循环队列的基本原理

 把顺序队列所使用的存储空间构造成一个逻辑上首尾相连的循环队列。当rear和front达到MaxQueueSize-1后,再前进一个位置就自动到0。

在这里插入图片描述

3.2、顺序循环队列的队空和队满判断问题

新问题:在循环队列中,空队特征是front=rear;队满时也会有front=rear;判决条件将出现二义性!
解决方案有三:
①使用一个计数器记录队列中元素个数(即队列长度);
  判队满:count>0 && rearfront; countMaxQueueSize
判队空:count0
②加设标志位,出队时置0,入队时置1,则可识别当前front=rear属于何种情况
判队满:tag
1 && rearfront
判队空:tag
0 && rearfront
③ 少用一个存储单元
  队满: front==(rear+1)%MaxQueueSize
判队空: rear
front

3.3、顺序循环队列的实现

//顺序循环队列的结构体定义如下:
typedef struct
{
	DataType queue[MaxQueueSize];
	int rear;  //队尾指针
	int front;  //队头指针
	int count;  //计数器
} SeqCQueue; 

//(1)初始化QueueInitiate(Q)
void QueueInitiate(SeqCQueue *Q)
{
	Q->rear = 0;		
	Q->front = 0;
	Q->count = 0;
}

//(2)非空否QueueNotEmpty(Q)
//判断循环队列Q非空否,非空则返回1,否则返回0
int QueueNotEmpty(SeqCQueue Q)
{
	if(Q.count != 0)	return 1;
	else return 0;
}

//(3)入队列QueueAppend(Q, x)
//把数据元素值x插入顺序循环队列Q的队尾,成功返回1,失败返回0
int QueueAppend(SeqCQueue *Q, DataType x)
{
	if(Q->count > 0 && Q->rear == Q->front)
	{	
		printf("队列已满无法插入! \\n");
		return 0;
	}
	else
	{	
		Q->queue[Q->rear] = x;
		Q->rear = (Q->rear + 1) % MaxQueueSize;
		Q->count++;
		return 1;
	}
}

//(4)出队列  QueueDelete(Q, d)
//删除顺序循环队列Q的队头元素并赋值给d,成功则返回1,失败返回0
int QueueDelete(SeqCQueue *Q, DataType *d)
{
	if(Q->count == 0)
	{	printf("队列已空无数据元素出队列! \\n");
		return 0;
	}
	else
	{	*d = Q->queue[Q->front];
		Q->front = (Q->front + 1) % MaxQueueSize;
		Q->count--;
		return 1;
	}
}

//(5)取队头数据元素 QueueGet(Q, d)
int QueueGet(SeqCQueue Q, DataType *d)
{
	if(Q.count == 0)
	{
		printf("队列已空无数据元素可取! \\n");
		return 0;
	}
	else
	{
		*d = Q.queue[Q.front];
		return 1;
	}
}

四、链式存储结构的队列

链式队列的存储结构
链式队列的队头指针指向队列的当前队头结点;队尾指针指在队列的当前队尾结点.

不带头结点的链式队列的结构如下:
在这里插入图片描述

//结点的结构体可定义如下:
typedef struct qnode
{
	DataType data;
	struct qnode *next;
} LQNode; 	
					
//队头指针front和队尾指针rear的结构体类型:
typedef struct
{
	LQNode *front;	//队头指针					
	LQNode *rear;	//队尾指针					
} LQueue;

//(1)初始化  QueueInitiate(Q)
void QueueInitiate(LQueue *Q)
{
	Q->rear = NULL;	                //队头指针
	Q->front = NULL;	                //队尾指针
}

//(2)非空否QueueNotEmpty(Q)
int QueueNotEmpty(LQueue Q)
{
	if(Q.front == NULL) return 0;
	else return 1;
}

//(3)入队列   QueueAppend(Q, x)
int QueueAppend(LQueue *Q, DataType x)
{
	LSNode *p;
 	p = (LQNode *)malloc(sizeof(LQNode)) ; 
	p->data = x;
	p->next = NULL;
	if(Q->rear != NULL) Q->rear->next = p;  //队列非空时,队尾增加新结点
	Q->rear = p;  //修改队尾指针
	if(Q->front == NULL) Q->front = p; //队列原来为空时修改队头指针
	if(Q->front==NULL){Q->rear= p; Q->front= p;}
	else {
	 	Q->rear->next = p; 	 Q->rear = p; 
	}
	return 1;
}

//(4)出队列 QueueDelete(Q, d)
int QueueDelete(LQueue *Q, DataType *d)
{
	LQNode *p;
	if(Q->front == NULL)
	{	
		printf("队列已空无数据元素出队列! \\n");	
		return 0;
	}
	else
	{	
		*d = Q->front->data;
		p = Q->front;
		Q->front = Q->front->next;
		//只有一个结点,删除之后队列为空,修改尾指针
		if(Q->front == NULL) Q->rear = NULL; 				
		free(p);
		return 1;
	}
}

//(5)取队头数据元素QueueGet(Q, d)
int QueueGet(LQueue Q, DataType *d)
{
	if(Q.front == NULL)
	{	printf("队列已空无数据元素出队列! \\n");
		return 0;
	}
	else
	{
		*d = Q.front->data;
		return 1;
	}
}

五、优先级队列:带有优先级的队列。

5.1、优先级队列和一般队列的主要区别

优先级队列的出队列操作不是把队头元素出队列,而是把队列中优先级最高的元素出队列。

struct DataType   
{                    
	 ElemType elem;     //数据元素	
     int priority;      //优先级
};

/*出队列操作
(把优先级最高的元素出队列并由函数返回,优先级相同时按先进先出的原则出队列。取顺序优先队列中优先级最高的元素算法类同)*/
int QueueDelete(SeqPQueue *Q, DataType *d)
//删除优先级队列Q中优先级最高的元素
{
	DataType min;
	int minIndex, i;
 	if(Q->size <= 0)
	{
		printf("队列已空无数据元素出队列! \\n");
		return 0;
	}	
	else
	{	
		min = Q->queue[0];
		minIndex = 0;
		for(i = 1; i < Q->size; i++){
	        if(Q->queue[i].priority < min.priority)
			{	
				min = Q->queue[i];
				minIndex = i;
			}
		}
 		*d = Q->queue[minIndex];
		for(i = minIndex+1; i < Q->size; i++){
			Q->queue[i-1] = Q->queue[i];
		}
 
		Q->size--;		
		return 1;
	}
}

//取优先级最高的元素
int QueueGet(SeqPQueue *Q, DataType *d)
{
	DataType min;
	int minIndex i;
	if(Q->size<=0)
	{
		printf(“”)
		return 0;
	}
	else
	{
		min=Q->queue[0];
		minIndex =0;
		for(i=1;i<Q->size;i++)
		if(Q->queue[i].priority<min.priority)
		{
			min=Q->queue[i];
			minIndex =i;
		}
	*d=Q->queue[minIndex];
	return 1;
	}
}

以上是关于C语言数据结构——队列的主要内容,如果未能解决你的问题,请参考以下文章

C语言代码片段

C/C++语言数据结构快速入门(代码解析+内容解析)队列的应用

数据结构(使用C语言)队列

(C语言)手撕数据结构之——队列

数据结构——链式队列解析(C语言版)

新手向C语言实现特殊数据结构——队列(含用两个队列实现栈)