<队列>的概念&结构&实现【C语言版】

简介: <队列>的概念&结构&实现【C语言版】

0.png

正文


1.队列的概念及结构


队列对于临时数据的处理也十分有趣,它跟栈一样都是有约束条件的数组(或者链表)。区别在于我们想要按什么顺序去处理数据,而这个顺序当然是要取决于具体的应用场景。


你可以将队列想象成是电影院排队。排在最前面的人会最先离队进入影院。套用到队列上,就是首先加入队列的,将会首先从队列移出。


因此计算机科学家都用缩写“FIFO”(first in, first out)先进先出,来形容它。


与栈类似,队列也有 3个限制(但内容不同)。


 ▶ 只能在末尾插入数据(这跟栈一样)。

 ▶ 只能读取开头的数据(这跟栈相反)。

 ▶ 只能移除开头的数据(这也跟栈相反)。


下面来看看它是怎么运作的,先准备一个空队列。


首先,插入 5(虽然栈的插入就叫压栈,但队列的插入却没有固定的叫法,一般可以叫放入、加入、入队)。

43.png

然后,插入 9。

44.png

接着,插入 100。


45.png


目前为止,队列表现得还跟栈一样,但要是移除数据的话,就会跟栈反着来了,因为队列是从开头移除数据的。


想移除数据,得先从 5 开始,因为开头就是它。

34.png

接着,移除 9。

33.png

这样一来,队列就只剩下 100了。


2.队列的实现


队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。


2.1队列结构的定义


typedef struct Queue
{
  QNode* head; //记录队头的位置
  QNode* tail; //记录队尾的位置
  int size; //记录队列的长度
}Queue;


2.2队列中存储数据的结点


typedef int QDataType;
typedef struct QueueNode
{
  QDataType data; //存储的数据
  struct QueueNode* next; //记录下一个结点的位置
}QNode;


2.3函数接口的实现


首先是在Queue.h文件中进行函数声明


Queu.h


#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedef int QDataType;
typedef struct QueueNode
{
  QDataType data; //存储的数据
  struct QueueNode* next; //记录下一个结点的位置
}QNode;
typedef struct Queue
{
  QNode* head; //记录队头的位置
  QNode* tail; //记录队尾的位置
  int size; //记录队列的长度
}Queue;
//队列的初始化
void QueueInit(Queue* pq);
//释放malloc出的内存
void QueueDestroy(Queue* pq);
//入队
void QueuePush(Queue* pq, QDataType x);
//出队
void QueuePop(Queue* pq);
//获取队头的数据
QDataType QueueFront(Queue* pq);
//获取队尾的数据
QDataType QueueBack(Queue* pq);
//判断队列是否为空
bool QueueEmpty(Queue* pq);
//队列数据的个数
int QueueSize(Queue* pq);

在Queue.c文件中进行函数的定义


Queue.c


#define _CRT_SECURE_NO_DEPRECATE 1
#include"Queue.h"
void QueueInit(Queue* pq)
{
  assert(pq);
  pq->head = NULL;
  pq->tail = NULL;
  pq->size = 0;
}
void QueueDestroy(Queue* pq)
{
  assert(pq);
  //用cur找尾
  QNode* cur = pq->head;
  while (cur)
  {
    QNode* del = cur;
    cur = cur->next;
    free(del);
  }
  pq->size = 0;
  pq->head = pq->tail = NULL;
}
void QueuePush(Queue* pq,QDataType data)
{
  assert(pq);
  QNode* newNode = (QNode*)malloc(sizeof(QNode));
  if (newNode == NULL)
  {
    perror("malloc fail");
    exit(-1);
  }
  //初始化结点
  newNode->data = data;
  newNode->next = NULL;
  if (pq->tail == NULL)
  {
    //队列为空时入队
    pq->head = newNode;
    pq->tail = newNode;
  }
  else
  {
    //队列不为空时入队
    pq->tail->next = newNode;
    pq->tail = newNode;
  }
  pq->size++;
}
void QueuePop(Queue* pq)
{
  assert(pq);
  assert(!QueueEmpty(pq));
  if (pq->head->next == NULL)
  {
    //只有一个结点时
    free(pq->head);
    pq->head = pq->tail = NULL;
  }
  else
  {
    //一般情况
    QNode* del = pq->head;
    pq->head = pq->head->next;
    free(del);
  }
  pq->size--;
}
QDataType QueueFront(Queue* pq)
{
  assert(pq);
  assert(!QueueEmpty(pq));
  return pq->head->data;
}
QDataType QueueBack(Queue* pq)
{
  assert(pq);
  assert(!QueueEmpty(pq));
  return pq->tail->data;
}
bool QueueEmpty(Queue* pq)
{
  assert(pq);
  //return pq->size==0;
  return pq->head == NULL && pq->tail == NULL;
}
int QueueSize(Queue* pq)
{
  assert(pq);
  return pq->size;
}


目录
相关文章
|
22小时前
|
C语言
C语言之分支结构
C语言之分支结构
23 0
|
22小时前
|
C语言
顺序队列的初始化、进队和出队(C语言)
顺序队列的初始化、进队和出队(C语言)
15 1
|
22小时前
|
C语言
C语言结构体内存对齐
C语言结构体内存对齐
|
23小时前
|
存储 编译器 Linux
【C语言】自定义类型:结构体深入解析(二)结构体内存对齐&&宏offsetof计算偏移量&&结构体传参
【C语言】自定义类型:结构体深入解析(二)结构体内存对齐&&宏offsetof计算偏移量&&结构体传参
|
22小时前
|
C语言
【精通C语言】:分支结构if语句的灵活运用
【精通C语言】:分支结构if语句的灵活运用
24 1
|
22小时前
|
编译器 Linux C语言
C语言:结构体(自定义类型)知识点(包括结构体内存对齐的热门知识点)
C语言:结构体(自定义类型)知识点(包括结构体内存对齐的热门知识点)
|
22小时前
|
编译器 C语言
c语言概念
c语言概念
|
22小时前
|
Java C语言 C++
C语言中用switch语句实现多分支选择结构
C语言中用switch语句实现多分支选择结构
21 0
|
22小时前
|
存储 缓存 C语言
初阶数据结构之---栈和队列(C语言)
初阶数据结构之---栈和队列(C语言)
|
22小时前
|
存储 程序员 C语言
C语言指针的概念、语法和实现
在C语言中,指针是其最重要的概念之一。 本文将介绍C语言指针的概念、语法和实现,以及如何使用它们来编写高效的代码。
14 0

热门文章

最新文章