【算法与数据结构】队列的实现详解

这篇具有很好参考价值的文章主要介绍了【算法与数据结构】队列的实现详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【算法与数据结构】队列的实现详解,数据结构;从练气期到筑基期,算法,数据结构,c语言,队列,开发语言


📝队列的概念及结构

  1. 队列的概念:
    队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out) 新添加的元素添加到队尾,只能从队头取出元素。
    入队列:进行插入操作的一端称为队尾
    出队列:进行删除操作的一端称为队头
    【算法与数据结构】队列的实现详解,数据结构;从练气期到筑基期,算法,数据结构,c语言,队列,开发语言
  2. 队列特征如下:

入队(Enqueue):通过尾指针添加元素到队列尾部,即向队列中插入元素。

出队(Dequeue):通过头指针删除队列头部元素,即从队列中移除元素。

空队列:当头指针和尾指针相同时,表示队列为空。

满队列:当尾指针指向队列容量最大位置时,表示队列已满。

  1. 常用的队列结构包括数组和链表实现:

数组实现队列:使用一维数组存储元素,头指针和尾指针分别指向数组的下标位置。

链表实现队列:每个元素使用一个节点存储,头节点和尾节点通过指针链接实现队列。

🌠 队列的顺序实现

头文件:Queue_order.h

# define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>

#define MAX_SIZE 100

typedef int QDataType;

typedef struct Queue
{
	QDataType data[MAX_SIZE];
	int front;
	int rear;
	int size;//记录队列中元素数量
}Queue;

//初始化队列
void InitQueue(Queue* pq);
//入队操作
void EnQueue(Queue* pq,int value);
//出队
QDataType DeQueue(Queue* pq);
//获取队首元素
QDataType FrontQueue(Queue* pq);
//获取队尾元素
QDataType RearQueue(Queue* pq);

//获取队列中有效元素个数
QDataType SizeQueue(Queue* pq);
//队列是否为空
QDataType IsEmpty(Queue* pq);
//队列是否为满
QDataType IsFull(Queue* pq);
//销毁队列
void DestroyQueue(Queue* pq);

🌉初始化

【算法与数据结构】队列的实现详解,数据结构;从练气期到筑基期,算法,数据结构,c语言,队列,开发语言

//初始化队列
void InitQueue(Queue* pq)
{
	pq->front = -1;
	pq->rear = -1;
	pq->size = 0;
}

front和rear都指向-1,表示队列中没有数据。size为0,表示队列中没有元素。

🌠入队

//入队
void EnQueue(Queue* pq, int value)
{
	if (pq->front == MAX_SIZE - 1)
	{
		printf("队列满了,入队操作失败");//检查队列是否已满,如果front指针指向的下一个位置就是MAX_SIZE-1,表示队列已满,打印错误信息并返回。
		return;
	}
	if (pq->front == -1)
	{//如果front为-1,表示队列为空,将front指针置0。
		pq->front = 0;
	}
	pq->rear++;//如果front为-1
	pq->data[pq->rear] = value;//表示队列为空
	pq->size++;//加完了别忘了size++
}

🌉出队

//出队
QDataType DeQueue(Queue* pq)
{
	if (-1 == IsEmpty)
	{
		printf("队列为空!");
		return -1;//返回一个特定的值表示队列为空
	}
	int value = pq->data[pq->front];
	pq->front++;
	pq->size--;
	return value;
}

【算法与数据结构】队列的实现详解,数据结构;从练气期到筑基期,算法,数据结构,c语言,队列,开发语言
检查满是为了防止入队越界,front-1时,表示队列为空,需要将front置0,rear后移一位指向新的元素位置,将元素值写入data数组,size计数增加。

🌠获取队列首元素

//获取队首元素
QDataType FrontQueue(Queue* pq)
{
	if (-1 == IsEmpty)
	{
		printf("队列为空!");
		return -1;//返回一个特定的值表示队列为空
	}
	return pq->data[pq->front];
}

🌉获取队列尾部元素

//获取队列尾部元素
QDataType RearQueue(Queue* pq)
{
	if (0 == IsEmpty)
	{
		printf("队列为空!");
		return -1;//返回一个特定的值表示队列为空
	}
	return pq->data[pq->rear];
}

🌠获取队列中有效元素个数

//获取队列中有效元素个数
QDataType SizeQueue(Queue* pq)
{
	return pq->size;
}

🌉 队列是否为空

//队列是否为空
QDataType IsEmpty(Queue* pq)
{
	if (pq->front == -1 || (pq->front > pq->rear))
	{
		//队列为空
		return -1;
	}
	else
	{
		//队列不为空
		return 1;
	}
	
}

注意:在队列中,如果 front 指针大于 rear 指针,表示队列为空。这是因为 front 指针指向队列的第一个元素,而 rear 指针指向队列的最后一个元素。如果 front 指针大于 rear 指针,意味着队列中没有元素,或者已经出队了所有的元素。
考虑一个队列中有一个元素的情况。初始时 front 和 rear 都指向该元素,而当该元素出队时,front 指针会被移动到下一个位置,这时 front 指针就比 rear 指针大,表示队列已经为空。

🌠查看队列是否为满

//查看队列是否为满
QDataType IsFull(Queue* pq)
{
	return (pq->rear == MAX_SIZE - 1);
}

🌉销毁队列

//销毁队列
void DestroyQueue(Queue* pq)
{
	InitQueue(pq);//重新初始化队列,清空元素并释放内存
}

🌠测试

源文件Test.c

# define _CRT_SECURE_NO_WARNINGS 1
#include"Queue_order.h"

int main()
{
	Queue Pq;
	InitQueue(&Pq);

	EnQueue(&Pq, 10);
	EnQueue(&Pq, 20);
	EnQueue(&Pq, 30);
	
	printf("Front element: %d\n", FrontQueue(&Pq));
	printf("Rear element: %d\n", RearQueue(&Pq));
	printf("Front element: %d\n", SizeQueue(&Pq));
	printf("Front element: %d\n", FrontQueue(&Pq));

	printf("Dequeued element: %d\n", DeQueue(&Pq));
	printf("Dequeued element: %d\n", DeQueue(&Pq));
	printf("Dequeued element: %d\n", DeQueue(&Pq));
	printf("Dequeued element: %d\n", DeQueue(&Pq)); // 尝试从空队列中出队

	printf("Queue size: %d\n", SizeQueue(&Pq));
	printf("Is queue empty? %s\n", IsEmpty(&Pq) ? "Yes" : "No");
}

【算法与数据结构】队列的实现详解,数据结构;从练气期到筑基期,算法,数据结构,c语言,队列,开发语言

🌉 顺序队列的假溢出

顺序队列的假溢出指的是,队列在结构上没有真正满溢,但是在逻辑上已经无法再插入新元素了。
在队尾指针已经指向数组的最后一个位置,但数组中仍然有空闲空间时,确实是队列溢出的情况,而不是假溢出。这种情况通常是由于没有充分利用队列所分配的存储空间所导致的,因此会造成队列操作的限制。

“假溢出” 通常用于表示队列中还有空闲空间,但因某种原因无法继续插入元素的情况,这可能是由于某些限制条件或错误的队列操作所导致的。例如,可能存在对队列的错误管理,使得无法正确地判断队列是否已满,导致了插入元素失败的情况。
举个例子:
【算法与数据结构】队列的实现详解,数据结构;从练气期到筑基期,算法,数据结构,c语言,队列,开发语言

在一个顺序队列中,队列大小为5,已包含四个元素 value1-2-3-4,rear在队尾4的位置。
当出队两个元素value1-2时,队列前面多出来了两位置
【算法与数据结构】队列的实现详解,数据结构;从练气期到筑基期,算法,数据结构,c语言,队列,开发语言
当你想再插入来两个数据时,队列确只能插入一个数据,但是队列其实不能插入数据了。
这是队列在结构上没有真正满溢,但是在逻辑上已经无法再插入新元素了。
【算法与数据结构】队列的实现详解,数据结构;从练气期到筑基期,算法,数据结构,c语言,队列,开发语言
怎么优化这个假溢出呢?两种常见的方法:

  1. 循环队列: 循环队列是一种特殊的顺序队列,通过将队列的数组视为一个循环的环形结构,使得在队列尾部插入元素时可以利用数组头部的空闲空间,从而解决了假溢出的问题。循环队列中,当队尾指针指向数组的末尾时,再插入元素时将其指向数组的起始位置,这样就形成了一个循环。通过这种方式,可以充分利用数组空间,避免了假溢出。
  2. 动态扩容: 动态扩容是在顺序队列满时,自动增加数组的大小以容纳更多元素。当队列满时,分配一个更大的数组,并将原有的元素复制到新数组中,然后释放原来的数组。这样可以确保队列始终有足够的空间来插入新的元素,从而避免假溢出。动态扩容的关键是选择适当的扩容策略,以及控制扩容时机,以避免频繁的扩容操作带来的性能开销。

🌠循环队列概念

循环队列是一种基于数组实现的队列数据结构,其特点是通过循环利用数组空间来实现队列的操作。循环队列的数组通常被看作一个环形的结构,队列的头部和尾部指针在数组中循环移动,使得当尾部指针到达数组末尾时,可以将其“循环”到数组的起始位置,从而避免了溢出或假溢出的情况。
【算法与数据结构】队列的实现详解,数据结构;从练气期到筑基期,算法,数据结构,c语言,队列,开发语言

循环队列看似循环,其实是固定数组不断往复的过程,我们可以模拟普通数组来实现:
【算法与数据结构】队列的实现详解,数据结构;从练气期到筑基期,算法,数据结构,c语言,队列,开发语言
如图:data 表示一个数据域,int 为类型,当然你也可以修改为任意自定义的类型,也可以是复杂的结构体类型。
MAX_SIZE :表示循环最大容量,可进行放数据的操作空间
rear代表尾指针,入队时移动。
front代表头指针,出队时移动。
size记录当前有效数据的多少

代码:

#define MAX_SIZE 5

typedef struct {
    int data[MAX_SIZE];
    int front; // 队列头指针
    int rear;  // 队列尾指针
    int size;  // 队列当前元素个数
} Cir_Queue;

🌉循环队列的初始化

对于循环队列来说,front从0开始是合理的,因为数据数组是环状结构,front从0开始可以实现队列元素的循环利用。
rear从0开始表示队列此时为空,front和rear指针都指向数组第一个位置。
将队列当前元素个数size清零,表示队列为空。

// 初始化队列
void initQueue(Cir_Queue* queue) 
{
    queue->front = 0;将队列头指针front设置为0。
    queue->rear = 0;将队列尾指针rear也设置为0。
    queue->size = 0;
}

🌠循环队列的入队操作

入队操作与顺序队列相同,只需将rear向后移动。但要注意,如果rear达到队列的上限,需从头开始移动。建议使用余数法,确保操作在队列空间内进行,避免一次错误导致整体崩溃。
【算法与数据结构】队列的实现详解,数据结构;从练气期到筑基期,算法,数据结构,c语言,队列,开发语言
要进行入队操作,得先判断队列是不是满了rear==front来判断队空,也可以用size。

// 入队操作
void enqueue(Cir_Queue* queue, int value) 
{
    if (queue->size == MAX_SIZE) 
    {
        printf("Queue is full. Enqueue operation failed.\n");
        return;
    }
    queue->data[queue->rear] = value;
    queue->rear = (queue->rear + 1) % MAX_SIZE; // 使用(rear+1)%MAX_SIZE更新rear指针,循环移动
    queue->size++;
}

检查队列是否已满,可通过判断size是否等于MAX_SIZE来确定。如果已满,则打印提示信息并返回;将数值value赋给data数组的rear索引位置,并使用(rear+1)%MAX_SIZE更新rear指针。这里使用模运算来实现rear指针的循环移动。当rear指向最后一个位置时,利用模运算使其指向第一个位置,实现循环利用数组。然后将size增加1,表示元素个数加1。

🌉 循环队列的出队操作

// 出队操作
int dequeue(Cir_Queue* queue)
 {
    if (queue->size == 0)
     {
        printf("Queue is empty. Dequeue operation failed.\n");
        return -1;
    }
    int value = queue->data[queue->front];
    queue->front = (queue->front + 1) % MAX_SIZE; // 循环移动
    queue->size--;
    return value;
}

使用(front+1)%MAX_SIZE更新front指针,这里也使用模运算实现front指针的循环移动。当front指向最后一个位置时,利用模运算让它指向第一个位置。

🌉 查看队首元素

// 查看队首元素
int front(Cir_Queue* queue) 
{
    if (queue->size == 0) 
    {
        printf("Queue is empty. Front operation failed.\n");
        return -1;
    }
    return queue->data[queue->front];
}

🌠查看队尾元素

// 查看队尾元素
int rear(Cir_Queue* queue) 
{
    if (queue->size == 0) 
    {
        printf("Queue is empty. Rear operation failed.\n");
        return -1;
    }
    return queue->data[(queue->rear - 1 + MAX_SIZE) % MAX_SIZE];
}

🌉查看队列是否为空

// 查看队列是否为空
int isEmpty(Cir_Queue* queue) 
{
    return (queue->size == 0);
}

🌠查看队列是否已满

// 查看队列是否已满
int isFull(Cir_Queue* queue) 
{
    return (queue->size == MAX_SIZE);
}

🌉 测试下循环队列

int main() {
    Cir_Queue queue;
    initQueue(&queue);

   
    enqueue(&queue, 10);
    enqueue(&queue, 20);
    enqueue(&queue, 30);
    enqueue(&queue, 40);
    

    printf("Front element: %d\n", front(&queue));

    printf("Dequeued element: %d\n", dequeue(&queue));
    printf("Dequeued element: %d\n", dequeue(&queue));
    printf("Dequeued element: %d\n", dequeue(&queue));
    enqueue(&queue, 80);
    enqueue(&queue, 90);
    printf("Front element: %d\n", front(&queue));
    printf("rear element: %d\n", rear(&queue));

    return 0;
}

【算法与数据结构】队列的实现详解,数据结构;从练气期到筑基期,算法,数据结构,c语言,队列,开发语言


🚩总结

感谢你的收看,如果文章有错误,可以指出,我不胜感激,让我们一起学习交流,如果文章可以给你一个小小帮助,可以给博主点一个小小的赞😘

【算法与数据结构】队列的实现详解,数据结构;从练气期到筑基期,算法,数据结构,c语言,队列,开发语言文章来源地址https://www.toymoban.com/news/detail-850328.html

到了这里,关于【算法与数据结构】队列的实现详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【数据结构与算法】用队列实现栈

      🧑‍🎓 个人主页:简 料   🏆 所属专栏:C++   🏆 个人社区:越努力越幸运社区   🏆 简       介: 简料简料,简单有料~在校大学生一枚,专注C/C++/GO的干货分享,立志成为您的好帮手 ~ C/C++学习路线 (点击解锁) ❤️ C语言阶段(已结束) ❤️ 数据结构与算法(ing) ❤

    2024年01月15日
    浏览(37)
  • 【数据结构与算法】7、队列(Queue)的实现【用栈实现队列】

    ☘️ 队列 (Queue)是一种特殊的 线性表 , 只能在头尾两端进行操作 🎁 队尾(rear):只能从 队尾添加 元素,一般叫做 enQueue , 入队 🎁 队头(front):只能从 队头移除 元素,一般叫做 deQueue , 出队 🎁 先进先出 的原则, F irst I n F irst O ut, FIFO ☘️ 队列内部的实现可

    2024年02月12日
    浏览(43)
  • 【数据结构】队列(Queue)的实现 -- 详解

    1、概念 队列 :只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有 先进先出 FIFO(First In First Out)。 入队列 :进行 插入 操作的一端称为 队尾 。 出队列 :进行 删除 操作的一端称为 队头 。 2、结构 (1)队列的顺序存储结构 入队 ,不需要

    2024年02月15日
    浏览(38)
  • 数据结构与算法之Python实现——队列

    在上一期博客中我们学习了栈这种结构,本期博客将学习一下跟栈很类似的一种结构——队列。 本期知识点: 顺序队列 循环队列 链式队列 队列的应用 ⚪️ 什么是队列? 队列是一种跟栈很相似的结构。我们知道栈是一种 先进后出 的结构,那么队列就像一个排队的队伍一样

    2024年02月06日
    浏览(45)
  • 【数据结构和算法】---栈和队列的互相实现

    具体题目可以参考 LeetCode 232. 用栈实现队列 首先要想到的是,队列是一种 先进先出 的结构,而栈是一种 先进后出 的结构。依此 我们可以定义两个栈结构来模拟先进先出 ,既然要定义两个栈,那么为了方便调用,我们可以将这两个栈结构定义在一个结构体中,如下: 实现

    2024年02月03日
    浏览(42)
  • 【数据结构】队列篇| 超清晰图解和详解:循环队列模拟、用栈实现队列、用队列实现栈

    博主简介: 努力学习的22级计算机科学与技术本科生一枚🌸 博主主页: @是瑶瑶子啦 每日一言🌼: 每一个不曾起舞的日子,都是对生命的辜负。——尼采 🔗622. 设计循环队列 👧🏻 思路: 🍊数据结构: 使用数组为数据结构,且采用牺牲一个空间的方法来包装判空和判满的

    2024年02月11日
    浏览(39)
  • (详解)数据结构-----------栈与队列 c语言实现

    本章将会详细讲解以下知识点: 目录 一:栈         1:栈的定义,栈的特点         2:用什么结构来实现栈与原因的分析?         3:  (超详解)栈的常用接口并且附上测试用例 二:队列         1:队列的定义,队列的特点         2:用什么结构来实现队列与原因的分析

    2024年02月11日
    浏览(44)
  • 【算法与数据结构】232、LeetCode用栈实现队列

    所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。    思路分析 :这道题要求我们用栈模拟队列(工作上一定没人这么搞)。程序当中,push函数很好解决,直接将元素push进输入栈当中。pop函数需要实现队列先进先出的操作,而栈是先进后出。只

    2024年02月12日
    浏览(43)
  • 【数据结构】队列实现+层序遍历详解+一些练题

    欢迎来到我的: 世界 希望作者的文章对你有所帮助,有不足的地方还请指正,大家一起学习交流 ! 国庆到了,也要内卷一下,感谢所以老铁们的支持!😎 1、队列的定义 队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。 队列是一种先进先出(

    2024年02月08日
    浏览(38)
  • 【数据结构】如何用队列实现栈?图文详解(LeetCode)

    LeetCode链接:225. 用队列实现栈 - 力扣(LeetCode) 本文默认读者已经掌握栈与队列的基本知识 或者先看我的另一篇博客:【数据结构】栈与队列_字节连结的博客-CSDN博客 由于我们使用的是C语言,不能直接使用队列的操作, 所以做这道题得先把我们之前实现的队列复制过来:

    2024年02月12日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包