C语言数据结构--队列

时间:2024-10-12 06:56:40

C语言数据结构--队列

  • 基本概念
  • 链队列
    • 原理
    • 基本操作
      • 队列的链式存储结构
      • 初始化队列InitQueue
      • 入队列EnQueue
      • 出队列DeQueue
      • 销毁队列
      • 输出队列元素
      • 链队列基本操作代码
  • 循环队列
    • 原理
    • 基操
      • 初始化循环队列InitQueue
      • 入队列EnQueue
      • 出队列DeQueue
      • 求栈长度QueueLength
      • 输出队列元素display
      • 完整程序

基本概念

队列是一种 先进先出(FIFO)的线性表
顾名思义,就和排队一样,先加入队伍的人先离开队伍,后加入队伍的人后离开队伍
队列只允许在队尾插入元素,在队头删除元素
在这里插入图片描述
既然队列是线性表的一种,那么肯定也有两种存储形式
链队列 ——链式映像
循环队列——顺序映像

栈一般使用顺序表来实现,队列一般使用链表实现,即链队列

链队列

原理

用链表表示的队列简称为链队列
一个链队列需要两个分别指示对头和队尾的阵阵才能唯一确定。

在这里插入图片描述

基本操作

队列的链式存储结构

#include <>
#include <>
#include <>
#define ERROR -1;
#define OK 1;
typedef char QElemType;

typedef struct QNode{
     //结点类型
	QElemType data;    //队列中结点的数据域
	struct QNode *next;//结点的指针域
}QNode,*QueuePtr; 

typedef struct{
           //链队列类型
	QueuePtr front;    //队头指针
	QueuePtr rear;     //队尾指针
}LinkQueue;

注意,我们队头指针指向链队列的头结点,队尾指针指向终端结点(虽然头结点不是必须,但为了方便操作,我们一般加上头结点)

初始化队列InitQueue

示意图:
在这里插入图片描述
代码

LinkQueue *InitQueue(){
   
	LinkQueue *Q = (LinkQueue *)malloc(sizeof(LinkQueue));
	Q->front = Q->rear = (QueuePtr)malloc(sizeof(QNode));
	
	Q->front->next = NULL;
	printf("初始化队列成功!\n");
	return Q;
}

入队列EnQueue

入队列是从队尾插入元素,就像排队,肯定是从队尾排队。
如何找到队尾呢?
这就要用到队尾指针了。
示意图:
在这里插入图片描述

在这里插入图片描述
代码

/**
 * 入队列
 * 1. 创建一个新结点分配内存
 * 2. 初始化新结点
 * 3. 插入新结点并移动队尾指针
 */
Status EnQueue(LinkQueue *Q, QElemType *e) {
   

	//创建一个新结点并分配内存
	QueuePtr T = (QueuePtr)malloc(sizeof(QNode));
	if(!T){
   
		printf("分配内存失败!");
		exit(OVERFLOW);
	}

	//初始化新结点
	T->data = e;
	T->next = NULL;

	//插入新结点并移动队尾指针
	Q->rear->next = T;
	Q->rear = T;

	return OK;
}

注意
⭐⭐⭐⭐⭐
代码里有一段代码

	Q->rear->next = T;//将新元素插入到队列末尾
	Q->rear = T;//队尾指针移动位置

我刚开始直接使用 Q->rear = p;错过了前面一步。前面的一步是必不可少的。
因为第一步代码是先将队列插入,第二步是移动队尾指针位置,两者并不重复。都很重要。

出队列DeQueue

思考思路:
1)判断是否为空队列
2)出队列即从队头删除元素,是不是似曾相识的感觉,没错,出栈和出队列的原理几乎相同。
示意图:
在这里插入图片描述
程序

/**
 * 出队列
 * 1. 判断队列是否为空 
 * 2. 删除队首元素
 * 3. 如果刚刚删除的是最后一个元素,将该队列置空
 * 4. 释放空间
 */
Status DeQueue(LinkQueue *Q, QElemType *e){
   

	QueuePtr p;

	//判断队列是否为空
	if(Q->front == Q->rear) {
   
		printf("队列为空!");
		exit(OVERFLOW);
	}
	
	//删除队首元素
	p = Q->front->next;
	*e = p->data;
	Q->front->next = p->next;

	//如果刚刚删除的是最后一个元素,将该队列置空
	if(Q->rear == p){
   
		Q->rear = Q->front;//这里无所谓顺序,也可以写成 Q->front = Q->rear
	}

	free(q);

	retu