从零开始学数据结构系列之第二章《队》

文章目录


队列简介

​    队列只允许在队列头进行删除操作 ,在队列尾进行插入操作 ,当队列中没有元素时,称为空队列在队列中插入元素称为入队,从队列中删除元素称为出队 。因为队列只允许在尾端插入,在头端删除,所以只有最早进入队列的元素才能最先从队列中删除,即队列有 先进先出 的特点。

  • 队列是一种操作受限的线性表,队列只允许在表的一端进行插入,在表的另一端进行删除。可进行插入的一段称为队尾,可进行删除的一端称为队头。
  • 队列的主要特点就是先进先出。依照存储结构可分为:顺序队和链式队。

队列的特点

  • 队列为一种特殊的线性表,

  • 表的前端(front)进行删除操作,在表的后端(rear)进行插入操作,

  • 进行插入操作的端称为队尾,进行删除操作的端称为队头

  • 队列中没有元素时,称为空队列。

  • 队列的数据元素又称为队列元素

  • 在队列中插入一个队列元素称为入队

  • 从队列中删除一个队列元素称为出队

  • 因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中删除,故队列又称为先进先出

顺序队列

​   即仅在队头进行删除在队尾进行插入,可用地址连续的存储单元依次存放队列中的数据,比如数组。队头和队尾的位置是变化的,所以要设置头、尾指针。

​   初始化时的头尾指针,均置为 0。 当头尾指针相等时队列为空或者为满,在非空队列里,头指针始终指向队头元素,尾指针始终指向队尾元素的下一位置。

​   由队列的原理可以将头指针当做读操作,将尾指针当做写操作,即在尾端插入数据就是写入队列,在头端删除数据就是将队列中的数据读出,这样好理解点。

​ 刚开始头指针和尾指针都在同一位置

当队列入队时,尾指针加一,头指针保持不变,a1入队,尾指针rear+1指向下一个地址空间 ,即尾指针始终指向队尾的下一地址,如a4入队后,尾指针rear+1 。

队列出队时,尾指针保持不变,头指针依次加1 ,由先进先出原则,a1先入队,则a1先被读走,然后front+1,指向了 a2,a2删除后,front+1指向了 a3。

a5删除后,头指针和尾指针的指向又相同相等了,即说明队列中的数据 已经全部读走

在顺序队列中,当尾指针已经指向了队列的最后一个位置的下一位置时,如果再有元素入队,就会发生"溢出"此时队列中已经填满了数据,头指针还在开始位置。

顺序队列的 "假溢出" :即队列的存储空间并未填满,却发生了溢出。

比如 rear 现在指向了最后一个位置的下一位置,按照上面所说此时队列已经被填满,如果再有元素入队,就会发生"溢出",但这是在头指针没有移动的前提下,如果之前队列头也删除了一些元素,那么队列头指针经过n次的 +1 之后,会遗留下了很多空地址,但是顺序队列就会认为再有元素入队,就溢出,即出现 "假溢出" 现象,这是不合理的。

其实就是类似与尾插法,和栈的差别可以简单的理解为:

  • 插入方式不同,一个类似与头插法,一个类似于尾插法
  • 弹出方式的话,这两个其实差不多,基本可以用相同的方法实现
c 复制代码
#include <stdio.h>
#include <stdlib.h>


typedef struct Node 
{
	int data;
	struct Node *next;
} Node;


Node* initQueue() 
{
	Node* node = (Node*)malloc(sizeof(Node));
	node->data=0;
	node->next=NULL;
	return node;
}

/* 
	插入步骤,类似与尾插法
*/
void enQueue(Node* list, int data) 
{
	Node* node = (Node*)malloc(sizeof(Node));
	
	Node* head = list;
	node->data=data;

	while(list->next)list=list->next;
	node->next=list->next;
	list->next=node;

	head->data++;
}

/* 
	判断数据是否为空
*/
int isEmpty(Node* list) 
{
	if(list->data)
		return 1;
	else
		return 0;
}


/* 
	弹出数据,数据先进先出,后进后出
*/
int deQueue(Node* list) 
{
	int data;
	if(isEmpty(list))
	{
		Node* head = list;
		Node* node = list->next;
		data = node->data;
		list->next=node->next;
		free(node);
		head->data--;
		return data;
	}
	else
		return EOF;
}


void printQueue(Node* Q)
{
	Node* node = Q -> next;
    while (node) 
	{
        printf("%d -> ", node -> data);
        node = node -> next;
    }
    printf("NULL\n");
}


int main() 
{
	Node* Q = initQueue();
    enQueue(Q, 1);
    enQueue(Q, 2);
    enQueue(Q, 3);
    enQueue(Q, 4);
    printQueue(Q);
    printf("dequeue = %d\n", deQueue(Q));
    printf("dequeue = %d\n", deQueue(Q));
    printQueue(Q);
    return 0;
}

往期回顾

1.【第一章】《线性表与顺序表》
2.【第一章】《单链表》
3.【第一章】《单链表的介绍》
4.【第一章】《单链表的基本操作》
5.【第一章】《单链表循环》
6.【第一章】《双链表》
7.【第一章】《双链表循环》
8.【第二章】《栈》

相关推荐
l1t1 小时前
利用DeepSeek实现服务器客户端模式的DuckDB原型
服务器·c语言·数据库·人工智能·postgresql·协议·duckdb
l1t3 小时前
利用美团龙猫用libxml2编写XML转CSV文件C程序
xml·c语言·libxml2·解析器
Hello_Embed4 小时前
STM32HAL 快速入门(二十):UART 中断改进 —— 环形缓冲区解决数据丢失
笔记·stm32·单片机·学习·嵌入式软件
咸甜适中4 小时前
rust语言 (1.88) 学习笔记:客户端和服务器端同在一个项目中
笔记·学习·rust
Grassto5 小时前
RAG 从入门到放弃?丐版 demo 实战笔记(go+python)
笔记
Magnetic_h5 小时前
【iOS】设计模式复习
笔记·学习·ios·设计模式·objective-c·cocoa
风中的微尘6 小时前
39.网络流入门
开发语言·网络·c++·算法
研梦非凡6 小时前
ICCV 2025|从粗到细:用于高效3D高斯溅射的可学习离散小波变换
人工智能·深度学习·学习·3d
西红柿维生素7 小时前
JVM相关总结
java·jvm·算法
limengshi1383927 小时前
机器学习面试:请介绍几种常用的学习率衰减方式
人工智能·学习·机器学习