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

文章目录


队列简介

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

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

队列的特点

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

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

相关推荐
清木!3 分钟前
数据仓库详解
笔记
.YM.Z30 分钟前
C语言——文件操作
c语言·文件操作
@小红花37 分钟前
从0到1学习Vue框架Day03
前端·javascript·vue.js·学习·ecmascript
先做个垃圾出来………1 小时前
差分数组(Difference Array)
java·数据结构·算法
mysla1 小时前
嵌入式学习day45-硬件—汇编
汇编·学习
hansang_IR1 小时前
【题解】洛谷 P4286 [SHOI2008] 安全的航线 [递归分治]
c++·数学·算法·dfs·题解·向量·点积
乐迪信息1 小时前
乐迪信息:AI摄像机在智慧煤矿人员安全与行为识别中的技术应用
大数据·人工智能·算法·安全·视觉检测
GanGuaGua1 小时前
Linux系统:线程的互斥和安全
linux·运维·服务器·c语言·c++·安全
永日456701 小时前
学习日记-HTML-day51-9.9
前端·学习·html
多恩Stone2 小时前
【3DV 进阶-2】Hunyuan3D2.1 训练代码详细理解下-数据读取流程
人工智能·python·算法·3d·aigc