数据结构与算法学习笔记(三)-----队列(上)


前言

队列(Queue)是一种受限的线性表,它是一种运算受限的线性表,遵循先进先出(FIFO First In First Out)的原则:
1.队列是一种受限的线性结构
2.它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作。
生活中队列场景随处可见: 比如在电影院, 商场, 或者厕所排队…


一、队列的顺序存储

采用数组来保存队列的元素,设立一个队首指针 front ,一个队尾指针 rear,分别指向队首和队尾元素。则rear-front 即为存储的元素个数!
在这里插入图片描述

1.顺序队列的创建

#define MAX_SIZE 5		//队列的最大容量

typedef int Datatype; 	//队列中元素类型

typedef struct Queue	
{
	Datatype queue[MAX_SIZE];
	int front;	//队头指针 
	int rear;	//队尾指针 
}SeqQueue;

2.队列的初始化

void InitQueue(SeqQueue *SQ)	//初始化队列 
{
	if(!SQ)
	{
		cout<<"内存分配失败!"<<endl; 
		return ; 
	}
	SQ->front=SQ->rear=0; 	//初始时,front与rear都指向队头
}

3.队列的判空

int IsEmpty(SeqQueue *SQ)		//判断队列是否为空 
{
	if(!SQ)
		return 0;
	if(SQ->front==SQ->rear)		//此时队列为空
		return 1;
    return 0;
} 

4.队列的判满

在这里插入图片描述

int IsFull(SeqQueue *SQ)		//判断队列是否满了 
{
	if(!SQ)
		return 0;
	if(SQ->rear==MAX_SIZE)		//此时队列为满
		return 1;
	return 0;
}

5.元素入队

队列只能在尾部进行元素入队!

int EnterQueue(SeqQueue *SQ,Datatype data)		//元素入队
{
	if(!SQ)
		return 0;
	if(IsFull(SQ))
		return 0;
	SQ->queue[SQ->rear]=data;	//元素入队(入rear指针指向的位置)
	SQ->rear++;		//rear指针后移一位
	return 1;
}

6.元素出队

出队方式有两种,第一种是将队首元素移出队列,后面元素向前移动一位,弊端是会大量移动元素。
在这里插入图片描述

int DeleteQueue1(SeqQueue* SQ,Datatype* data)	//删除front指向的元素,front指向元素之后的元素向前移1,需要移动大量元素 
{
	if(!SQ||!data)
		return 0;
	if(IsEmpty(SQ))		
	{
		cout<<"队列为空!"<<endl;
		return 0;
	}
	*data=SQ->queue[SQ->front];
	for(int i=SQ->front+1;i<SQ->rear;i++)	//将front指向元素的后面元素向前移一位
		SQ->queue[i-1]=SQ->queue[i];
	SQ->rear--;
	return 1;
}

第二种是将front指针想队尾方向移动一位,达到删除目的,弊端是队列会越来越小

在这里插入图片描述

int DeleteQueue2(SeqQueue* SQ,Datatype* data)	//直接将front后移,队列会越来越小 
{
	if(!SQ||!data)
		return 0;
	if(IsEmpty(SQ))		
	{
		cout<<"队列为空"<<endl;
		return 0;
	}
	*data=SQ->queue[SQ->front];
	SQ->front=(SQ->front)+1;	//front指针向后移一位即可
	return 1;
}

7.获取队首元素

int GetHead(SeqQueue* SQ)	//获取队首元素 
{
	if(!SQ||IsEmpty(SQ))
		cout<<"队列为空!"<<endl;
	return SQ->queue[SQ->front];	//返回队首元素
}

8.元素打印

void PrintQueue(SeqQueue* SQ)	//队列元素打印
{
	if(!SQ)
		return ;
	if(IsEmpty(SQ))		 
		return ;
	int i=SQ->front;
	while(i<(SQ->rear))
	{
		cout<<setw(4)<<SQ->queue[i];
		i++;
	}
}

9.完整源码

#include <stdio.h>
#include <assert.h>
#include <iostream>
#include <iomanip>

#define MAX_SIZE 5

using namespace std;
typedef int Datatype; 

typedef struct Queue
{
	Datatype queue[MAX_SIZE];
	int front;	//队头指针 
	int rear;	//队尾指针 
}SeqQueue;

void InitQueue(SeqQueue *SQ)	//初始化队列 
{
	if(!SQ)
	{
		cout<<"内存分配失败!"<<endl; 
		return ; 
	}
	SQ->front=SQ->rear=0; 
}

int IsEmpty(SeqQueue *SQ)		//判断队列是否为空 
{
	if(!SQ)
		return 0;
	if(SQ->front==SQ->rear)
		return 1;
    return 0;
} 

int IsFull(SeqQueue *SQ)		//判断队列是否满了 
{
	if(!SQ)
		return 0;
	if(SQ->rear==MAX_SIZE)
		return 1;
	return 0;
}

int EnterQueue(SeqQueue *SQ,Datatype data)
{
	if(!SQ)
		return 0;
	if(IsFull(SQ))
		return 0;
	SQ->queue[SQ->rear]=data;
	SQ->rear++;
	return 1;
}

void PrintQueue(SeqQueue* SQ)
{
	if(!SQ)
		return ;
	if(IsEmpty(SQ))		 
		return ;
	int i=SQ->front;
	while(i<(SQ->rear))
	{
		cout<<setw(4)<<SQ->queue[i];
		i++;
	}
}

int DeleteQueue1(SeqQueue* SQ,Datatype* data)	//删除front元素,front后的元素向前移1,需要移动大量元素 
{
	if(!SQ||!data)
		return 0;
	if(IsEmpty(SQ))		//之前出错是因为手误写成if(IsFull(SQ))
	{
		cout<<"队列为空!"<<endl;
		return 0;
	}
	*data=SQ->queue[SQ->front];
	for(int i=SQ->front+1;i<SQ->rear;i++)
		SQ->queue[i-1]=SQ->queue[i];
	SQ->rear--;
	return 1;
}

int DeleteQueue2(SeqQueue* SQ,Datatype* data)	//直接将front后移,队列会越来越小 
{
	if(!SQ||!data)
		return 0;
	if(IsEmpty(SQ))		//之前出错是因为手误写成if(IsFull(SQ))
	{
		cout<<"队列为空"<<endl;
		return 0;
	}
	*data=SQ->queue[SQ->front];
	SQ->front=(SQ->front)+1;
	return 1;
}

int GetHead(SeqQueue* SQ)	//获取队首元素 
{
	if(!SQ||IsEmpty(SQ))
		cout<<"队列为空!"<<endl;
	return SQ->queue[SQ->front];
}

void DestroyQueue(SeqQueue* SQ)		//清空队列 
{
	SQ->front=SQ->rear=0;
}

int main()
{
	SeqQueue *SQ = new SeqQueue;
	Datatype data = -1;
	
	//初始化队列
	InitQueue(SQ);
	
	//入队
	for(int i=0; i<7; i++)
	{
		EnterQueue(SQ, i);
	}
	
	PrintQueue(SQ);
	cout<<endl;
	
	//出队
	if(DeleteQueue1(SQ, &data))
	{
		cout<<"出队的元素是:"<<data<<endl;
	}
	else
	{
		cout<<"出队失败!"<<endl;
	}
	if(DeleteQueue2(SQ, &data))
	{
		cout<<"出队的元素是:"<<data<<endl;
	}
	else
	{
		cout<<"出队失败!"<<endl;
	}
	
	//打印队列中的元素
	printf("出队一个元素后,队列中剩下的元素:");
	PrintQueue(SQ);
	cout<<endl;
	
	return 0;
}

在这里插入图片描述

二、队列的链式存储

队列的链式存储结构,其实就是线性表的单链表,只不过它只是尾进头出而已,我们把它简称为链队列。为了操作上的方便,我们将队头指针指向链队列的头结点,而队尾指针指向终端节点。
在这里插入图片描述

1.链式队列的创建

#define MAX_SIZE 5
typedef int DataType;

typedef struct _QNode
{
	DataType data;
	struct _QNode *next;
}QNode;

typedef QNode* QueuePtr;

typedef struct Queue
{
	int length;		//队列长度 
	QueuePtr front;	//队头指针 
	QueuePtr rear;	//队尾指针 
}LinkQueue;

2.队列的初始化

void InitQueue(LinkQueue *LQ)	//初始化队列 
{
	if(!LQ)
		return ;
	LQ->length=0;
	LQ->front=LQ->rear=NULL;	//头指针与尾指针均置空
}

3.队列的判空与元素入队

在这里插入图片描述

int IsEmpty(LinkQueue *LQ)	//判断队列是否为空 
{
	if(!LQ)
		return 0;
	if(LQ->front==NULL)
		return 1;
	return 0; 
}

int EnterQueue(LinkQueue *LQ,DataType data)		//入队 
{
	if(!LQ)
		return 0;
	if(IsFull(LQ))
	{
		cout<<"无法插入元素"<<data<<",队列已满"<<endl;
		return 0;
	}
	
	QNode *qNode=new QNode;
	qNode->data=data;
	qNode->next=NULL;
	
	if(IsEmpty(LQ))
	{
		LQ->front=LQ->rear=qNode;
	}
	else
	{
		LQ->rear->next=qNode;
		LQ->rear=qNode;
	}
	LQ->length++;
	return 1;
}

4.队列的判满

int IsFull(LinkQueue *LQ)	//判断队列是否满 
{
	if(!LQ)
		return 0;
	if(LQ->length==MAX_SIZE)
	{
		return 1;
	}
	return 0;
}

5.元素出队

在这里插入图片描述

int DeleteQueue(LinkQueue *LQ,DataType *data)	//元素出队
{
	QNode *tmp=NULL;
	if(!LQ||IsEmpty(LQ))
	{
		cout<<"队列为空!"<<endl;
		return 0;
	}
	if(!data)
		return 0;
	tmp=LQ->front;
	
	LQ->front=tmp->next;
	if(!LQ->front)
		LQ->rear=NULL;
	*data=tmp->data;
	LQ->length--;
	delete tmp;
	return 1;
}

6.获取队首元素

int GetHead(LinkQueue *LQ,DataType *data)	//获取队首元素 
{
	if(!LQ||IsEmpty(LQ))
	{
		cout<<"队列为空!"<<endl;
		return 0;
	}
	
	if(!data)
		return 0;
		
	*data=LQ->front->data;
	return 1;
}

7.元素打印

void PrintQueue(LinkQueue *LQ)	//队列元素打印 
{
	QueuePtr tmp;
	if(!LQ)
		return ;
		
	if(LQ->front==NULL)
		cout<<"队列为空!"<<endl;
		
	tmp=LQ->front;
	while(tmp)
	{
		cout<<setw(4)<<tmp->data;
		tmp=tmp->next;	
	}
	cout<<endl;
}

8.完整源码

#include <iostream>
#include <stdio.h>
#include <iomanip>

#define MAX_SIZE  5

using namespace std;
typedef int DataType;

typedef struct _QNode
{
	DataType data;
	struct _QNode *next;
}QNode;

typedef QNode* QueuePtr;

typedef struct Queue
{
	int length;		//队列长度 
	QueuePtr front;	//队头指针 
	QueuePtr rear;	//队尾指针 
}LinkQueue;

void InitQueue(LinkQueue *LQ)	//初始化队列 
{
	if(!LQ)
		return ;
	LQ->length=0;
	LQ->front=LQ->rear=NULL;
}

int IsEmpty(LinkQueue *LQ)	//判断队列是否为空 
{
	if(!LQ)
		return 0;
	if(LQ->front==NULL)
		return 1;
	return 0; 
}

int IsFull(LinkQueue *LQ)	//判断队列是否满 
{
	if(!LQ)
		return 0;
	if(LQ->length==MAX_SIZE)
	{
		return 1;
	}
	return 0;
}

int EnterQueue(LinkQueue *LQ,DataType data)		//入队 
{
	if(!LQ)
		return 0;
	if(IsFull(LQ))
	{
		cout<<"无法插入元素"<<data<<",队列已满"<<endl;
		return 0;
	}
	
	QNode *qNode=new QNode;
	qNode->data=data;
	qNode->next=NULL;
	
	if(IsEmpty(LQ))
	{
		LQ->front=LQ->rear=qNode;
	}
	else
	{
		LQ->rear->next=qNode;
		LQ->rear=qNode;
	}
	LQ->length++;
	return 1;
}

int DeleteQueue(LinkQueue *LQ,DataType *data)
{
	QNode *tmp=NULL;
	if(!LQ||IsEmpty(LQ))
	{
		cout<<"队列为空!"<<endl;
		return 0;
	}
	if(!data)
		return 0;
	tmp=LQ->front;
	
	LQ->front=tmp->next;
	if(!LQ->front)
		LQ->rear=NULL;
	*data=tmp->data;
	LQ->length--;
	delete tmp;
	return 1;
}

void PrintQueue(LinkQueue *LQ)	//队列元素打印 
{
	QueuePtr tmp;
	if(!LQ)
		return ;
		
	if(LQ->front==NULL)
		cout<<"队列为空!"<<endl;
		
	tmp=LQ->front;
	while(tmp)
	{
		cout<<setw(4)<<tmp->data;
		tmp=tmp->next;	
	}
	cout<<endl;
}

int GetHead(LinkQueue *LQ,DataType *data)	//获取队首元素 
{
	if(!LQ||IsEmpty(LQ))
	{
		cout<<"队列为空!"<<endl;
		return 0;
	}
	
	if(!data)
		return 0;
		
	*data=LQ->front->data;
	return 1;
}

void ClearQueue(LinkQueue *LQ)	//链队列销毁 
{
	if(!LQ)
		return ;
		
	while(LQ->front)
	{
		QueuePtr tmp=LQ->front->next;
		delete LQ->front;
		LQ->front=tmp;
	}
	
	LQ->front=LQ->rear=NULL;
	LQ->length=0;
}

int getLength(LinkQueue *LQ)	//队列长度
{
	if(!LQ)
		return 0;
	return LQ->length;
}

int main()
{
	LinkQueue *LQ=new LinkQueue;
	DataType data=-1;
	
	InitQueue(LQ);	//初始化队列 
	
	for(int i=0;i<7;i++)	//入队 
		EnterQueue(LQ,i);
		
	printf("队列中的元素(总共%d个):",getLength(LQ));	//打印队列元素 
	PrintQueue(LQ);
	cout<<endl;
	
	 if(DeleteQueue(LQ,&data))	//出队 
	 	cout<<"出队元素是:"<<data<<endl;
	else
		cout<<"出队失败!"<<endl;
	
	printf("队列中的元素(总共%d个):",getLength(LQ));	//打印队列元素 
	PrintQueue(LQ);
	cout<<endl;
	
	ClearQueue(LQ);
	cout<<"清空队列!"<<endl;
	PrintQueue(LQ);
	
	return 0;
}

在这里插入图片描述


总结

以上是对队列的初步讲解,如有误处,还请指正。后续还会介绍一些特殊队列。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值