C语言数据结构005——队列

一、队列的基本概念

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

示意图如下:
C语言数据结构005——队列_第1张图片

二、顺序存储结构的队列

有6个存储空间的顺序队列动态示意图
C语言数据结构005——队列_第2张图片

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

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

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

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

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

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

C语言数据结构005——队列_第4张图片

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;
	}
}

你可能感兴趣的:(#,数据结构与算法,队列,数据结构,算法,链表)