【数据结构】14 队列(带头结点的链式存储和顺序存储实现)

定义

队列是一个有序线性表,但是队列的插入、删除操作是分别在线性表的两个不同端点进行的。

设一个队列 Q = ( a 1 , a 2 , . . . , a n ) Q = (a_1, a_2,...,a_n) Q=(a1,a2,...,an),那么 a 1 a_1 a1被称为队头元素, a n a_n an为队尾元素。假如将元素A,B,C,D依次插入队列,第一个从队列中删除的元素为A,即先插入的将被先删除,故队列也称为先进先出表。

抽象数据类型
类型名称 :队列
数据对象集 :一个有0个或者多个元素的有穷线性表
操作集 :对于一个长度为正整数MaxSize的队列 Q Q Q, 记队列中的任一元素 X X X,队列的基本操作集为:

  1. Queue CreateQueue(int MaxSize)
  2. bool IsFull(Queue Q)
  3. bool AddQ(Queue Q, ElementType X)
  4. bool Is Empty(Queue Q)
  5. ElementType DeleteQ(Queue Q)

队列的顺序存储实现

队列的最简单的表示方法是用数组。用数组存储队列有许多具体的方法。一般可以选择将队列头放数组下标小的位置,而将队列尾放在数组下标大的位置,并用两个变量Front和Rear分别指示队列的头和尾。一般把Front和Rear先初始化为-1。当有元素入队时,Rear向右移动一格,放入队尾元素;当有元素出队时,先将Front向右移动一格,再删除队首元素。

随着入队出队的进行会使整个队列整体向后移动这样就出现了如上图所示的现象,指针已经移到了最后,在再有元素入队时就会出现溢出,可是事实上此时队中并未真的满员,这种现象称为假溢出。

为了解决队尾溢出而实际上数组中仍有空余空间的问题,一般在队列的顺序存储结构中采用循环队列的方式,队尾指针和队首指针到达数组端点时能折回到数组开始处即相当于将数组头尾相接想象成环形,如图所示当插入和删除操作的作用单元达到数组的末端后用公式"Rear % 数组长度"取余运算就可以实现折返到起始单元。

队列初始化时,将Front和Rear都初始化为0,当插入一个元素时,Rear+1,删除一个元素时,Front加一。

当Front = Rear时,队列为空。

当队尾指针加1就会从后面赶上头指针,(Rear + 1)%数组长度 = Front

代码实现

顺序存储

数据结构

c 复制代码
typedef int ElementType;
typedef int Position;
typedef struct QNode* PtrToQNode;
struct QNode {
	ElementType* Data;
	Position Front, Rear;
	int MaxSize;
};
typedef PtrToQNode Queue;

创建循环队列

c 复制代码
Queue CreateQueue(int MaxSize) {
	Queue Q = (Queue)malloc(sizeof(struct QNode));
	Q->MaxSize = MaxSize;
	Q->Data = (ElementType*)malloc(sizeof(ElementType) * MaxSize);
	Q->Front = 0;
	Q->Rear = 0;
	return Q;
}

插入元素

c 复制代码
bool IsFull(Queue Q) {
	if ((Q->Rear + 1) % Q->MaxSize == Q->Front) {
		return true;
	}
	else {
		return false;
	}
}

bool AddQ(Queue Q, ElementType X) {
	if (IsFull(Q)) {
		printf("The Queue is full!\n");
		return false;
	}
	else {
		Q->Rear = (Q->Rear + 1) % Q->MaxSize;
		Q->Data[Q->Rear] = X;
		return true;
	}
}

删除元素

c 复制代码
bool IsEmpty(Queue Q) {
	if (Q->Rear == Q->Front) {
		return true;
	}
	else {
		return false;
	}
}


ElementType DeleteQ(Queue Q) {
	if (IsEmpty(Q)) {
		printf("The Queue is empty!\n");
		return -1;
	}
	else {
		Q->Front = (Q->Front + 1) % (Q->MaxSize);
		return Q->Data[(Q->Front)];


	}
}

完整代码

c 复制代码
# include <stdio.h>
#include < stdlib.h>
#include <ctype.h>
#include <string.h>

typedef int ElementType;
typedef int Position;
typedef struct QNode* PtrToQNode;
struct QNode {
	ElementType* Data;
	Position Front, Rear;
	int MaxSize;
};
typedef PtrToQNode Queue;


Queue CreateQueue(int MaxSize) {
	Queue Q = (Queue)malloc(sizeof(struct QNode));
	Q->MaxSize = MaxSize;
	Q->Data = (ElementType*)malloc(sizeof(ElementType) * MaxSize);
	Q->Front = 0;
	Q->Rear = 0;
	return Q;
}

bool IsFull(Queue Q) {
	if ((Q->Rear + 1) % Q->MaxSize == Q->Front) {
		return true;
	}
	else {
		return false;
	}
}


bool AddQ(Queue Q, ElementType X) {
	if (IsFull(Q)) {
		printf("The Queue is full!\n");
		return false;
	}
	else {
		Q->Rear = (Q->Rear + 1) % Q->MaxSize;
		Q->Data[Q->Rear] = X;
		return true;
	}
}


void printQ(Queue Q) {
	int f = Q->Front;
	int r = Q->Rear;
	while (f != r) {
		f = (f + 1) % (Q->MaxSize);
		printf("QNode: %d\n", Q->Data[f]);
	}
}

bool IsEmpty(Queue Q) {
	if (Q->Rear == Q->Front) {
		return true;
	}
	else {
		return false;
	}
}


ElementType DeleteQ(Queue Q) {
	if (IsEmpty(Q)) {
		printf("The Queue is empty!\n");
		return -1;
	}
	else {
		Q->Front = (Q->Front + 1) % (Q->MaxSize);
		return Q->Data[(Q->Front)];


	}
}

int main() {

	Queue Q = CreateQueue(10);
	ElementType X;
	int N;
	scanf_s("%d", &N);
	while (N--) {
		scanf_s("%d", &X);
		if (AddQ(Q, X) == false) {
			printf("Add error!\n");
		}

	}

	printQ(Q);
	while (!IsEmpty(Q)) {
		ElementType out = DeleteQ(Q);
		printf("Out : %d\n", out);
		printf("\n");
		printQ(Q);
	}
	



}

链式存储

队列的头必须指向的是队列的头结点,队尾指向链表的尾节点

数据结构

c 复制代码
typedef int ElementType;
typedef struct Node* PtrToNode;
struct Node {
	ElementType Data;
	PtrToNode Next;
};

typedef struct Node* Position;

struct QNode {
	Position Rear, Front;
	int MaxSize;
};
typedef struct QNode * Queue;

队列的创建

c 复制代码
Queue CreateQueue(int MaxSize) {
	Queue Q = (Queue)malloc(sizeof(struct QNode));
	Q->MaxSize = MaxSize;
	PtrToNode L = (PtrToNode)malloc(sizeof(struct Node));
	
	L->Next = NULL;
	Q->Front = L;
	Q->Rear = L;

	
	printf("finish!\n");

	return Q;


}

加入元素

c 复制代码
bool IsFull(Queue Q) {
	int cnt = 0;
	
	Position t = Q->Front;
	
	while (t != Q->Rear) {
		t = t->Next;
		cnt++;
	}
	printf("cnt : %d\n", cnt);
	if (cnt == Q->MaxSize) {
		return true;
	}
	else {
		return false;
	}
}


bool AddQ(Queue Q, ElementType X) {
	if (IsFull(Q)) {
		printf("The Queue is full!\n");
		return false;
	}

	Position R = Q->Rear;
	while (R->Next != NULL) {
		R = R->Next;
	}
	PtrToNode t = (PtrToNode)malloc(sizeof(struct Node));
	t->Data = X;
	t->Next = R->Next;
	R->Next = t;
	Q->Rear = t;

	return true;


}

删除元素

c 复制代码
bool IsEmpty(Queue Q) {
	if (Q->Front->Next == NULL) {
		return true;
	}
	else {
		return false;
	}
}

ElementType DeleteQ(Queue Q) {
	if(IsEmpty(Q)) {
		printf("The Queue is empty!\n");
		return -1;
	}
	else {

		ElementType t = Q->Front->Next->Data;
		Position te = Q->Front;
		Q->Front->Next = Q->Front->Next->Next;
		return t;
	}
}

完整代码

c 复制代码
# include <stdio.h>
#include < stdlib.h>
#include <ctype.h>
#include <string.h>

typedef int ElementType;
typedef struct Node* PtrToNode;
struct Node {
	ElementType Data;
	PtrToNode Next;
};

typedef struct Node* Position;

struct QNode {
	Position Rear, Front;
	int MaxSize;
};
typedef struct QNode * Queue;


Queue CreateQueue(int MaxSize) {
	Queue Q = (Queue)malloc(sizeof(struct QNode));
	Q->MaxSize = MaxSize;
	PtrToNode L = (PtrToNode)malloc(sizeof(struct Node));
	
	L->Next = NULL;
	Q->Front = L;
	Q->Rear = L;

	
	printf("finish!\n");

	return Q;


}

bool IsFull(Queue Q) {
	int cnt = 0;
	
	Position t = Q->Front;
	
	while (t != Q->Rear) {
		t = t->Next;
		cnt++;
	}
	printf("cnt : %d\n", cnt);
	if (cnt == Q->MaxSize) {
		return true;
	}
	else {
		return false;
	}
}


bool AddQ(Queue Q, ElementType X) {
	if (IsFull(Q)) {
		printf("The Queue is full!\n");
		return false;
	}

	Position R = Q->Rear;
	while (R->Next != NULL) {
		R = R->Next;
	}
	PtrToNode t = (PtrToNode)malloc(sizeof(struct Node));
	t->Data = X;
	t->Next = R->Next;
	R->Next = t;
	Q->Rear = t;

	return true;


}

void printq(Queue Q) {
	Position t = Q->Front;
	while (t != Q->Rear)
	{
		t = t->Next;
		printf("QNode: %d\n", t->Data);
	}

}

bool IsEmpty(Queue Q) {
	if (Q->Front->Next == NULL) {
		return true;
	}
	else {
		return false;
	}
}

ElementType DeleteQ(Queue Q) {
	if(IsEmpty(Q)) {
		printf("The Queue is empty!\n");
		return -1;
	}
	else {

		ElementType t = Q->Front->Next->Data;
		Position te = Q->Front;
		Q->Front->Next = Q->Front->Next->Next;
		return t;
	}
}

int main() {

	Queue Q = CreateQueue(10);

	ElementType X;
	int N;
	scanf_s("%d", &N);
	while (N--) {
		scanf_s("%d", &X);
		if (AddQ(Q, X) == false) {
			printf("Add error!\n");
		}

	}

	printq(Q);
	while (!IsEmpty(Q)) {
		int out = DeleteQ(Q);
		printf("\n");
		printf("Out : %d\n", out);
		//printq(Q);
	}
	


}
相关推荐
_.Switch19 分钟前
Python机器学习模型的部署与维护:版本管理、监控与更新策略
开发语言·人工智能·python·算法·机器学习
zengy539 分钟前
Effective C++中文版学习记录(三)
数据结构·c++·学习·stl
自由的dream1 小时前
0-1背包问题
算法
2401_857297912 小时前
招联金融2025校招内推
java·前端·算法·金融·求职招聘
良月澪二3 小时前
CSP-S 2021 T1廊桥分配
算法·图论
wangyue44 小时前
c# 线性回归和多项式拟合
算法
&梧桐树夏4 小时前
【算法系列-链表】删除链表的倒数第N个结点
数据结构·算法·链表
QuantumStack4 小时前
【C++ 真题】B2037 奇偶数判断
数据结构·c++·算法
今天好像不上班4 小时前
软件验证与确认实验二-单元测试
测试工具·算法
wclass-zhengge5 小时前
数据结构篇(绪论)
java·数据结构·算法