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

文章目录


队列简介

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

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

队列的特点

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

  • 表的前端(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.【第二章】《栈》

相关推荐
Code季风7 分钟前
深入理解令牌桶算法:实现分布式系统高效限流的秘籍
java·算法·微服务
KyollBM27 分钟前
【Luogu】每日一题——Day15. P1144 最短路计数 (记忆化搜索 + 图论 + 最短路)
算法·图论
Olrookie32 分钟前
若依前后端分离版学习笔记(一)——本地部署
笔记·后端·开源
一百天成为python专家35 分钟前
K-近邻算法
数据结构·python·算法·pandas·近邻算法·ipython·python3.11
满分观察网友z1 小时前
告别烦人的“三连发”:我的智能评论系统过滤之旅(1957. 删除字符使字符串变好)
算法
小新学习屋1 小时前
《剑指offer》-数据结构篇-哈希表/数组/矩阵/字符串
数据结构·leetcode·哈希表
满分观察网友z1 小时前
滑动窗口下的极限挑战:我在实时数据流中挖掘最大价值分(1695. 删除子数组的最大得分)
算法
PerfumerKarma1 小时前
【WebGPU学习杂记】数学基础拾遗(2)变换矩阵中的齐次坐标推导与几何理解
学习·线性代数·矩阵
knight_20241 小时前
嵌入式学习日志————对射式红外传感器计次
stm32·单片机·嵌入式硬件·学习
山烛1 小时前
KNN 算法中的各种距离:从原理到应用
人工智能·python·算法·机器学习·knn·k近邻算法·距离公式