追梦之旅【数据结构篇】——详解C语言实现顺序队列

简介: 前言🙌预备小知识🙌队列的概念及结构😊1.顺序队列头文件编写🙌2.Queue.c文件的编写🙌1)队列的初始化函数实现😊2)队列的销毁函数实现😊3)队尾入函数实现😊4)队头出函数实现😊5)取队首元素函数实现😊6)取队尾元素函数实现😊7)队列元素个数函数实现😊2)判空函数实现😊3.Test.c文件的编写:🙌总结撒花💞

微信图片_20230427214238.gif

😎博客昵称:博客小梦

😊最喜欢的座右铭:全神贯注的上吧!!!

😊作者简介:一名热爱C/C++,算法等技术、喜爱运动、热爱K歌、敢于追梦的小博主!

😘博主小留言:哈喽!😄各位CSDN的uu们,我是你的博客好友小梦,希望我的文章可以给您带来一定的帮助,话不多说,文章推上!欢迎大家在评论区唠嗑指正,觉得好的话别忘了一键三连哦!😘


image.gif


前言🙌



   哈喽各位友友们😊,我今天又学到了很多有趣的知识,现在迫不及待的想和大家分享一下!😘我仅已此文,手把手带领大家详解C语言实现顺序队列~ 结合链表的相关算法,根据队列先进先出的结构特点,实现我们顺序队列。都是精华内容,可不要错过哟!!!😍😍😍


预备小知识🙌


队列的概念及结构😊


队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出

FIFO(First In First Out)


入队列:进行插入操作的一端称为队尾

出队列:进行删除操作的一端称为队头

队列的结构示意图:

微信图片_20230427220149.png


1.顺序队列头文件编写🙌


头文件的编写的整体思路分析:

这里是有关头文件的编写和各种功能函数的声明,首先用typedef关键字给存储数据类型取别名,这样做的好处是以后想要改变队列的数据类型只需修改typedef int DataType;里的int即可。定义一个结构体,DataType a,DataType Top队首元素下标,DataType Last。DataType Capacity以及队列容量。然后是各个功能函数声明*

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef int DataType;
typedef struct SqQueue
{
  DataType* a;
  DataType Top;
  DataType Last;
  DataType Capacity;
}SQ;
//队列的初始化
void SqQueueInit(SQ* ps);
//队列的销毁
void SqQueueDestory(SQ* ps);
//队尾入
void SqQueuePush(SQ* ps, DataType x);
//队头出
void SqQueuePop(SQ* ps);
//取队首元素
DataType SqQueueFront(SQ* ps);
//取队尾元素
DataType SqQueueBack(SQ* ps);
//队列元素个数
DataType SqQueueSize(SQ* ps);
//判空
bool SqQueueEmpty(SQ* ps);


2.Queue.c文件的编写🙌


1)队列的初始化函数实现😊


编写的整体思路分析:

先用assert确保ps指针的有效性,然后让指针a为NULL,让队列容量,头尾下标都为0.

//队列的初始化
void SqQueueInit(SQ* ps)
{
  assert(ps);
  ps->a = NULL;
  ps->Capacity = 0;
  ps->Top = ps->Last = 0;
}


2)队列的销毁函数实现😊


编写的整体思路分析:

先用assert确保ps指针的有效性,然后将a指向的空间返还给操作系统。然后将a置为NULL,防止野指针的问题。然后让 ps->Last = ps->Top = ps->Capacity = 0;

/队列的销毁
void SqQueueDestory(SQ* ps)
{
  assert(ps); 
  free(ps->a);
  ps->a = NULL;
  ps->Last = ps->Top = ps->Capacity = 0;
}


3)队尾入函数实现😊


编写的整体思路分析:

先用assert确保ps指针的有效性,如果ps->Last == ps->Capacity,则让节点个数增加,为0的时候先生成四个节点数,如果满了则是增2倍算法思想。然后用realloc动态申请空间,用if判断是否增容成功。然后将指针a指向新开辟的空间所在的地址,把容量数值改为newnode。如果一开始为空的情况,则让ps->a[ps->Top] = ps->a[ps->Last] = x

//队尾入
void SqQueuePush(SQ* ps, DataType x)
{
  assert(ps);
  if (ps->Last == ps->Capacity)
  {
    DataType newnode = ps->Capacity == 0 ? 4 : ps->Capacity * 2;
    DataType* temp = (DataType*)realloc(ps->a,sizeof(DataType)*newnode);
    if (temp == NULL)
    {
      printf("realloc fail\n");
      exit(-1);
    }
    ps->a = temp;
    ps->Capacity = newnode;
  }
  if (ps->Last == ps->Top)
  {
    ps->a[ps->Top] = ps->a[ps->Last] = x;
    ps->Last++;
  }
  else
  {
    ps->a[ps->Last] = x;
    ps->Last++;
  }
}


4)队头出函数实现😊


编写的整体思路分析:

先用assert确保ps指针的有效性,调用判空函数,如果队列为空则不用执行此操作,执行则报错。直接让Top加1即可。

//队头出
void SqQueuePop(SQ *ps)
{
  assert(ps);
  assert(!SqQueueEmpty(ps));
  ps->Top++;
}


5)取队首元素函数实现😊


编写的整体思路分析:

先用assert确保ps指针的有效性,直接返回下标为Top的元素的数值。

//取队首元素
DataType SqQueueFront(SQ* ps)
{
  assert(ps);
  return ps->a[ps->Top];
}


6)取队尾元素函数实现😊


编写的整体思路分析:

先用assert确保ps指针的有效性,直接返回下标为Last-1的元素的数值。

//取队尾元素
DataType SqQueueBack(SQ* ps)
{
  return ps->a[ps->Last-1];
}


7)队列元素个数函数实现😊


编写的整体思路分析:

先用assert确保ps指针的有效性,直接返回下标为Last的数值。

//队列元素个数
DataType  SqQueueSize(SQ* ps)
{
  assert(ps);
  return ps->Last;
}


8)判空函数实现😊


编写的整体思路分析:

先用assert确保ps指针的有效性,如果 ps->Top ==ps->Last为真,则返回1,队列为空。条件为假,则返回0。

//判空
bool SqQueueEmpty(SQ* ps)
{
  assert(ps);
  return(ps->Top ==ps->Last);
}


3.Test.c文件的编写:🙌


#include"Queue.h"
void Test1()
{
  printf("队列输出:\n");
  SQ s;
  SqQueueInit(&s);
  SqQueuePush(&s, 1);
  SqQueuePush(&s, 2);
  SqQueuePush(&s, 3);
  SqQueuePush(&s, 4);
  SqQueuePush(&s, 5);
  SqQueuePush(&s, 6);
  SqQueuePush(&s, 7);
  while (!SqQueueEmpty(&s))
  {
    printf("%d", SqQueueFront(&s));
    SqQueuePop(&s);
  }
  printf("\n");
  SqQueueDestory(&s);
}
void Test2()
{
  SQ s;
  SqQueueInit(&s);
  SqQueuePush(&s, 1);
  SqQueuePush(&s, 2);
  SqQueuePush(&s, 3);
  SqQueuePush(&s, 4);
  SqQueuePush(&s, 5);
  SqQueuePush(&s, 6);
  SqQueuePush(&s, 7);
  printf("队列首元素:%d\n", SqQueueFront(&s));
  printf("队列尾元素:%d\n", SqQueueBack(&s));
  printf("队列元素个数:%d\n", SqQueueSize(&s));
  SqQueueDestory(&s);
}
int main()
{
  Test1();
  Test2();
  return 0;
}


功能测试结果展示图:

微信图片_20230427221004.png


总结撒花💞


   本篇文章旨在分享详解C语言实现顺序队列。希望大家通过阅读此文有所收获!😘如果我写的有什么不好之处,请在文章下方给出你宝贵的意见😊。如果觉得我写的好的话请点个赞赞和关注哦~😘😘😘

相关文章
|
27天前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
123 9
|
26天前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
63 16
|
26天前
|
C语言
【数据结构】二叉树(c语言)(附源码)
本文介绍了如何使用链式结构实现二叉树的基本功能,包括前序、中序、后序和层序遍历,统计节点个数和树的高度,查找节点,判断是否为完全二叉树,以及销毁二叉树。通过手动创建一棵二叉树,详细讲解了每个功能的实现方法和代码示例,帮助读者深入理解递归和数据结构的应用。
83 8
|
28天前
|
存储 C语言
【数据结构】手把手教你单链表(c语言)(附源码)
本文介绍了单链表的基本概念、结构定义及其实现方法。单链表是一种内存地址不连续但逻辑顺序连续的数据结构,每个节点包含数据域和指针域。文章详细讲解了单链表的常见操作,如头插、尾插、头删、尾删、查找、指定位置插入和删除等,并提供了完整的C语言代码示例。通过学习单链表,可以更好地理解数据结构的底层逻辑,提高编程能力。
54 4
|
28天前
|
C语言
【数据结构】双向带头循环链表(c语言)(附源码)
本文介绍了双向带头循环链表的概念和实现。双向带头循环链表具有三个关键点:双向、带头和循环。与单链表相比,它的头插、尾插、头删、尾删等操作的时间复杂度均为O(1),提高了运行效率。文章详细讲解了链表的结构定义、方法声明和实现,包括创建新节点、初始化、打印、判断是否为空、插入和删除节点等操作。最后提供了完整的代码示例。
41 0
|
18天前
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
22 1
|
5天前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
26 5
|
20天前
|
存储 算法 Java
数据结构的栈
栈作为一种简单而高效的数据结构,在计算机科学和软件开发中有着广泛的应用。通过合理地使用栈,可以有效地解决许多与数据存储和操作相关的问题。
|
23天前
|
存储 JavaScript 前端开发
执行上下文和执行栈
执行上下文是JavaScript运行代码时的环境,每个执行上下文都有自己的变量对象、作用域链和this值。执行栈用于管理函数调用,每当调用一个函数,就会在栈中添加一个新的执行上下文。
|
25天前
|
存储
系统调用处理程序在内核栈中保存了哪些上下文信息?
【10月更文挑战第29天】系统调用处理程序在内核栈中保存的这些上下文信息对于保证系统调用的正确执行和用户程序的正常恢复至关重要。通过准确地保存和恢复这些信息,操作系统能够实现用户模式和内核模式之间的无缝切换,为用户程序提供稳定、可靠的系统服务。
47 4