【栈、队列和数组之队列】


一、队列的基本概念

队列是一种操作比较受限的线性表,因为它只允许在表的一段进行插入,而在表的另一端进行删除。遵行的是一个先进先出的原则。
概念

二、队列的顺序存储结构

1.队列的顺序存储

队列的顺序存储也是跟栈和简单顺序表一样,在一开始需要定义元素存储的大小。之后设置两个指针,分别指向队头和队尾。队列的顺序存储类型为:

#define MaxSize 6  //定义队列中元素的最大个数
typedef int ElemType;
typedef struct {
	ElemType data[MaxSize];  //只能存放MaxSize-1个元素
	int front, rear;  //定义一个队头指针和一个队尾指针
}SqQueue;

(1)在定义一个队列元素的最大个数之后,真正可以存储数据的只有MaxSize-1个元素,因为需要拿出一个存储单元来使队尾指针指向它,不然在判断队空还是队满的时候,队头指针和队尾指针都指向一个存储单元之后会导致判断不了,如图所示:
判断
(2)当第一个元素入队时,队头指针就会一直指向它,除非它出队列了,而队尾指针则指向插入元素后的一个存储单元。每插入一个元素后,队尾指针都会向后移一个位置。而每当出队一个元素之后,队头指针也会往后移一个位置。

2.循环队列的操作

(1)初始化

//初始化
void InitQueue(SqQueue& Q)
{
	Q.front = Q.rear = 0;
}

(2)判断队列是否为空

//判断队列是否为空
bool isEmpty(SqQueue Q)
{
	if (Q.front == Q.rear)  //当队头、队尾指针指向同一个存储单元时队列为空
	{
		return true;
	}
	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;
}

插入数据之后设置一个断点可以看到插入的相应值,分别是2,3,4,5。
入队
(4)出队操作

//出队
bool DeQueue(SqQueue &Q, ElemType &x)
{
	if (Q.front == Q.rear)  //判断队列是否为空
	{
		return false;
	}
	x = Q.data[Q.front];
	Q.front = (Q.front + 1) % MaxSize;  //当队头弹出一个元素后,队头指针往后进1位
	return true;

}

出队

三、队列的链式存储结构

1.队列的链式存储

队列的链式又称为链队列,同时带有队头结点和队尾结点的单链表。
队列的链式存储结构类型为:

typedef int ElemType;
typedef struct LinkNode {  //链式队列结点
	ElemType data;
	struct LinkNode* next;
}LinkNode;
typedef struct {  //链式队列
	LinkNode* front, * rear;  //队列的队头和队尾指针
}LinkQueue;

2.链式存储的操作

(1)初始化

//初始化
void InitQueue(LinkQueue& Q)
{
	Q.front = Q.rear = (LinkNode*)malloc(sizeof(LinkNode));  //建立头结点
	Q.front->next = NULL;
}

(2)判断队列是否为空
当队头结点等于队尾结点的时候,则队列为空。

//判断是否为空
bool InEmpty(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;
}

设置一个断点查看入队的元素,分别为2,3,4,5。
入队

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

出队

四、完整代码

(1)队列的顺序存储

#include<stdio.h>
#include<stdlib.h>

#define MaxSize 6  //定义队列中元素的最大个数
typedef int ElemType;
typedef struct {
	ElemType data[MaxSize];  //只能存放MaxSize-1个元素
	int front, rear;  //定义一个队头指针和一个队尾指针
}SqQueue;

//初始化
void InitQueue(SqQueue& Q)
{
	Q.front = Q.rear = 0;
}

//判断队列是否为空
bool isEmpty(SqQueue Q)
{
	if (Q.front == Q.rear)
	{
		return true;
	}
	return false;
}

//入队操作
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;
}

//出队
bool DeQueue(SqQueue &Q, ElemType &x)
{
	if (Q.front == Q.rear)  //判断队列是否为空
	{
		return false;
	}
	x = Q.data[Q.front];
	Q.front = (Q.front + 1) % MaxSize;  //当对头弹出一个元素后,队头指针往后进1位
	return true;

}
int main()
{
	SqQueue Q;
	bool ret;
	ElemType element;
	InitQueue(Q);
	EnQueue(Q, 2);
	EnQueue(Q, 3);
	EnQueue(Q, 4);
	EnQueue(Q, 5);
	EnQueue(Q, 6);
	ret = EnQueue(Q, 7);  //已经超出了范围,所以7入不了队
	if (ret)
	{
		printf("入队成功\n");
	}
	else {
		printf("入队失败\n");
	}
	ret = isEmpty(Q);
	if (ret)
	{
		printf("队列为空\n");
	}
	else {
		printf("队列不为空\n");
	}
	ret= DeQueue(Q, element);
	if (ret)
	{
		printf("出队成功,元素值为%d\n",element);
	}
	else {
		printf("出队失败:\n");
	}
	ret = DeQueue(Q, element);
	if (ret)
	{
		printf("出队成功,元素值为%d\n", element);
	}
	else {
		printf("出队失败:\n");
	}
	return 0;
}

(2)队列的链式存储

#include<stdio.h>
#include<stdlib.h>
 
typedef int ElemType;
typedef struct LinkNode {  //链式队列结点
	ElemType data;
	struct LinkNode* next;
}LinkNode;
typedef struct {  //链式队列
	LinkNode* front, * rear;  //队列的队头和队尾指针
}LinkQueue;

//初始化
void InitQueue(LinkQueue& Q)
{
	Q.front = Q.rear = (LinkNode*)malloc(sizeof(LinkNode));
	Q.front->next = NULL;
}

//判断是否为空
bool InEmpty(LinkQueue Q)
{
	if (Q.front == Q.rear)
		return true;
	else
		return false;
}

//入队
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;
}

//出队
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;
}
int main()
{
	LinkQueue Q;
	bool ret;
	ElemType element;
	InitQueue(Q);
	EnQueue(Q, 2);
	EnQueue(Q, 3);
	EnQueue(Q, 4);
	EnQueue(Q, 5);
	ret = DeQueue(Q, element);
	if (ret)
	{
		printf("出队成功,出队元素为:%d\n", element);
	}
	else
	{
		printf("出队失败\n");
	}
	ret = DeQueue(Q, element);
	if (ret)
	{
		printf("出队成功,出队元素为:%d\n", element);
	}
	else
	{
		printf("出队失败\n");
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值