【数据结构】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);
	}
	


}
相关推荐
jiao_mrswang28 分钟前
leetcode-18-四数之和
算法·leetcode·职场和发展
qystca37 分钟前
洛谷 B3637 最长上升子序列 C语言 记忆化搜索->‘正序‘dp
c语言·开发语言·算法
薯条不要番茄酱37 分钟前
数据结构-8.Java. 七大排序算法(中篇)
java·开发语言·数据结构·后端·算法·排序算法·intellij-idea
今天吃饺子42 分钟前
2024年SCI一区最新改进优化算法——四参数自适应生长优化器,MATLAB代码免费获取...
开发语言·算法·matlab
是阿建吖!43 分钟前
【优选算法】二分查找
c++·算法
王燕龙(大卫)1 小时前
leetcode 数组中第k个最大元素
算法·leetcode
不去幼儿园2 小时前
【MARL】深入理解多智能体近端策略优化(MAPPO)算法与调参
人工智能·python·算法·机器学习·强化学习
Mr_Xuhhh2 小时前
重生之我在学环境变量
linux·运维·服务器·前端·chrome·算法
盼海3 小时前
排序算法(五)--归并排序
数据结构·算法·排序算法
网易独家音乐人Mike Zhou6 小时前
【卡尔曼滤波】数据预测Prediction观测器的理论推导及应用 C语言、Python实现(Kalman Filter)
c语言·python·单片机·物联网·算法·嵌入式·iot