数据结构学习之队列

简介: 数据结构学习之队列

前言:在我们学习了栈之后,明白了它的结构的特殊性即LAST IN FIRST OUT(后进先出),与之相对应的也有一个特殊的结构队列(queue)--FIRST IN FIRST OUT(先进先出),他们都是面对特殊情况下的数据的结构,那么队列有是如何实现的呢,是用来干嘛的呢?

1.什么是队列?

队列是一种先进先出的、操作受限的线性表。它的想法来自于生活中排队的策略,先来的元素先出去,后来的元素后出去。队列可以用数组或链表来实现,也有循环队列和优先队列等特殊类型,考虑到队列的先进先出的特点,即数据的头删尾插,我们选择用链表来实现队列,这里选用单链表即可。

队列的模型图:

484f218478bb483da987f3390ff4bcd9.png

日常生活中我们排队在餐厅门口处取餐,挂号都是一种队列的模型。

919d1dacbb8f4ca782dfe043fcca8bec.png

2.队列的实现

1.结构体与函数接口

和栈相反,对于队列因为只允许操作队头与队尾,我们除了创建单链表的结构体外,还创建了一个结构体表示队列,包含队头节点,队尾节点,以及队长,故这里的单链表结构体相当于是为我们提供节点,实现队列是在此基础上的该队列结构体。

其次便是实现的一些基本功能的接口。队列的实现整体较为简单,我们这里还是以存放整数为例。

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdbool.h>
#include<assert.h>
#include<stdlib.h>
typedef int queDATAtype;
typedef struct Queuenode
{
  struct Queuenode* next;
  queDATAtype data;
}QUE;
 typedef struct QUEue
{
  QUE* front;
  QUE* tail;
  int size;
}LTnode;
void Queueinit(LTnode* p);//初始化队列
void Queuedestroy(LTnode* p);//销毁队列
void LTpush(LTnode* p,int x);//尾插
void LTpop(LTnode* p);//头删
int  LTfront(LTnode* p);//返回队头
int  LTtail(LTnode* p);//返回队尾
int LTsize(LTnode* p);//返回队长
bool LTempety(LTnode* p);//判空队

2.初始化队列

初始化队列很简单,即我们的队头与队尾此时皆为空,长度为零。

//初始化
void Queueinit(LTnode* p)
{
  assert(p);
  p->front = NULL;
  p->tail = NULL;
  p->size = 0;
}

3.销毁队列

即从头开始遍历队列,不为空则释放,然后指向下一节点,(与头删一样,我们先保存下一节点,在释放)直到头尾节点皆被释放,之后置空,长度归零。

void Queuedestroy(LTnode* p)
{
  assert(p);
  QUE* cur = p->front;
  while (cur)
  {
    QUE* next =cur->next;
    free(cur);;
    cur = next;
  }
  p->front = p->tail = NULL;
  p->size = 0;
}

4.入队

入队即尾插,因为这里是无哨兵位的单链表,因此在判空队列之后,我们先开辟出节点空间并初始化为要插入的节点,然后再判断若为空节点,即没有元素,那么队头节点与队尾节点相等并为该插入的新节点,否则,就是尾插--与单链表操作类似,链接尾节点的next,之后成为新的尾节点。插入之后,记得队长加一。

void LTpush(LTnode* p, int x)
{
  QUE*newnode=(QUE*)malloc(sizeof(QUE));
  if (newnode == NULL)
  {
    return;
    perror("malloc fail");
  }
  assert(p);
  newnode->next = NULL;
  newnode->data = x;
  if (p->front ==NULL )
  {
    assert(p->tail==NULL);
    p->front = p->tail = newnode;
    p->size++;
  }
  else
  {
    p->tail->next = newnode;
    p->tail = newnode;
    p->size++;
  }
}

5.出队

出队,即头删,因此我们先判空队列之后,在判断是否有元素,即头尾指针不同时为零。头删时要分两种情况:1.只有一个元素时头删,这时我们要将头尾指针同时free置空。2.多个元素头删,保存头结点的下一个,free头节点,成为新的头节点。

void LTpop(LTnode* p)//头删
{
  assert(p);
  assert(!LTempety(p));
  if (p->front ->next==NULL)
  {
    free(p->front);
    p->front = NULL;
    p->tail = NULL;
  }
  else
  {
        QUE* cur = p->front->next; 
      free(p->front);
      p->front = cur;
  }
   p->size--;
}

以下四个操作较为简单,不做表述:

6.返回队头

int LTfront(LTnode* p)
{
  assert(p);
  assert(!LTempety(p));
  return p->front->data;
}

7.返回队尾

int  LTtail(LTnode* p)
{
  assert(p);
  return p->tail->data;
}

8.返回长度

int LTsize(LTnode* p)
{
  assert(p);
  return p->size;
}

9.判空队列

bool LTempety(LTnode* p)
{
  assert(p);
  return p->size == 0;
}

注意事项

这里需要注意的一点是,我们一般是不会对栈与队列的某个元素进行访问,必须遵循该结构对数据的操作方式,即数据只能先进先出。我们遍历数据也是如此:

int main()
{
  LTnode n;
  Queueinit(&n);
  LTpush(&n, 1);
  LTpush(&n, 2);
  LTpush(&n, 3);
  while (!LTempety(&n))
  {
    printf("%d ", LTfront(&n));
    LTpop(&n);
  }
  Queuedestroy(&n);
  return 0;
}

3.队列的用处

队列结构下的应用是指利用队列的特点来解决一些实际问题或算法问题。例如:

1.队列可以用来模拟排队等待的场景。

2.也可以用来实现广度优先搜索算法。

3.可以用来设计一些特殊的队列,如单调队列、优先队列等,来处理区间最值、滑动窗口等问题。


相关文章
|
5天前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
64 9
|
8天前
|
存储 算法 安全
2024重生之回溯数据结构与算法系列学习之串(12)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丟脸好嘛?】
数据结构与算法系列学习之串的定义和基本操作、串的储存结构、基本操作的实现、朴素模式匹配算法、KMP算法等代码举例及图解说明;【含常见的报错问题及其对应的解决方法】你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
2024重生之回溯数据结构与算法系列学习之串(12)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丟脸好嘛?】
|
8天前
|
算法 安全 搜索推荐
2024重生之回溯数据结构与算法系列学习(8)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第2.3章之IKUN和I原达人之数据结构与算法系列学习x单双链表精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
8天前
|
存储 算法 安全
2024重生之回溯数据结构与算法系列学习之顺序表【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
顺序表的定义和基本操作之插入;删除;按值查找;按位查找等具体详解步骤以及举例说明
|
8天前
|
算法 安全 搜索推荐
2024重生之回溯数据结构与算法系列学习之单双链表精题详解(9)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第2.3章之IKUN和I原达人之数据结构与算法系列学习x单双链表精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
8天前
|
存储 Web App开发 算法
2024重生之回溯数据结构与算法系列学习之单双链表【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构之单双链表按位、值查找;[前后]插入;删除指定节点;求表长、静态链表等代码及具体思路详解步骤;举例说明、注意点及常见报错问题所对应的解决方法
|
8天前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之栈和队列精题汇总(10)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第3章之IKUN和I原达人之数据结构与算法系列学习栈与队列精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
8天前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之顺序表习题精讲【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
顺序表的定义和基本操作之插入;删除;按值查找;按位查找习题精讲等具体详解步骤以及举例说明
|
8天前
|
存储 算法 安全
2024重生之回溯数据结构与算法系列学习【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构的基本概念;算法的基本概念、特性以及时间复杂度、空间复杂度等举例说明;【含常见的报错问题及其对应的解决方法】
|
27天前
初步认识栈和队列
初步认识栈和队列
57 10