IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 数据结构与算法(5.2)队列(附源码) -> 正文阅读

[数据结构与算法]数据结构与算法(5.2)队列(附源码)

在今天的学习中,将会介绍栈和队列的概念,以及其功能的实现,还有其应用场景


在这里插入图片描述

前言

队列是只允许再一端进行插入数据操作,另一端进行删除数据操作的特殊线性表,和栈不同的是,队列是先进先出的,进行插入的一端叫做队尾,出队列的一段叫做队头。

就像排队上公交车一样先排的肯定先进公交车,后来的就等着。
在这里插入图片描述
更简洁一点来说就是:
在这里插入图片描述

队列的实现

队列也是一种特殊的线性表,所以也可以用顺序表或者链表来实现,那么该选谁呢?这时候我们就要思考效率的问题,如果用顺序表的话,数组头就是队头,我要出队的话肯定是从数组头开始出,那么我后面的数据全要挪移,这复杂度就变成O(N)了,如果使用链表呢?用链表的话无论是入队还是出队,都只需要挪动前一个节点或者后一个节点的指向而已,所以我们选用链表来实现队列。
实现功能如下:

1.初始化队列

2.购买节点

3.入队

4.出队

5.检查队列是否为空

6.销毁队列

首先如果是链表的话,我们现要有一个节点的结构体:

typedef struct QListNode    
{                       
  struct QListNode* _next;    
  QDataType _data;    
}QNode;                   
                  
// 队列的结构           
typedef struct Queue         
{
  QNode* _front;         
  QNode* _rear;
}Queue; 

这里面有两个结构体,其中QNode是队列中每一个节点,Queue代表整个队列,其中存储队头和队尾。(有点头节点那意思了)

1.初始化队列

void QueueInit(Queue* q)
{
  q->_front = NULL;
  q->_rear = NULL;
}

2.购买节点

QNode * BuyQueueNode(QDataType x)
{
  QNode * cur = (QNode*)malloc(sizeof(QNode));
  cur->_data = x;
  cur->_next = NULL;
  return cur;
}

这是链表的节点,注意是队列的结构体存的结构体指针的类型,不是队列的类型

3.入队

void QueuePush(Queue* q, QDataType data)
{
  QNode * cur = BuyQueueNode(data);                                                                                                                                                       
  if(q->_front==NULL)
  {
      q->_front = q->_rear = cur;
  }
  else//有节点就在队列最后尾插,让rear后移一位 
  {
    q->_rear->_next = cur;
    q->_rear = cur;
  }
}

入队要分成两种情况,一种是队列中没有节点,一种是已经有节点了,没有节点的时候,我们直接让队头和队尾的指针都指向新节点就可以了,那有节点的时候呢?有节点的时候就和链表的尾插是一样的,但是要注意,此时rear存储的是队尾,我们尾插之后,要让rear后移一位成新队尾。
在这里插入图片描述
红色是我们新进队的节点,这时候队尾的指向就不对了,要指向新节点。

4.出队

void QueuePop(Queue* q)
{
    assert(q);//出队列就相当于链表的头删一样
    if(q->_front == NULL)
      return ;
    QNode *cur = q->_front->_next;
    free(q->_front);
    q->_front = cur;
}

出队就是头删,别忘了要把储存队头的指针后移一位。

检查队列是否为空

int QueueEmpty(Queue* q)
{
  if(q->_front == NULL)
    return 1;
  else return 0;
}

销毁链表

void QueueDestroy(Queue* q)
{
  if(q->_front == NULL)
    return ;
  while(q->_front)
  {
    QueuePop(q);
  }
}

销毁链表的时候就一直执行头删,删完为止。

应用:

有时候我们会用栈实现队列,队列实现栈,在实际应用中循环的队列是使用次数比较高的,在下一篇博客中将会介绍用队列实现栈,用栈实现队列,以及循环队列的写法。

源码

Queue.h

#include<stdio.h>      
#include<assert.h>    
#include<stdlib.h>    
typedef int QDataType;
// 链式结构:表示队列     
typedef struct QListNode
{
    struct QListNode* _next;
    QDataType _data;
}QNode;

// 队列的结构          
typedef struct Queue
{
    QNode* _front;
    QNode* _rear;
}Queue;

// 初始化队列     
void QueueInit(Queue* q);
// 队尾入队列     
void QueuePush(Queue* q, QDataType data);
// 队头出队列     
void QueuePop(Queue* q);
// 获取队列头部元素     
QDataType QueueFront(Queue* q);
// 获取队列队尾元素     
QDataType QueueBack(Queue* q);
// 获取队列中有效元素个数     
int QueueSize(Queue* q);
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0     
int QueueEmpty(Queue* q);
// 销毁队列     
void QueueDestroy(Queue* q);

Queue.c

#include"Queue.h"

// 链式结构:表示队列     
//typedef struct QListNode     
//{     
//  struct QListNode* _next;     
//  QDataType _data;     
//}QNode;              

// 队列的结构         
//typedef struct Queue     
///{                      
//  QNode* _front;          
//  QNode* _rear;      
//}Queue;                     

QNode* BuyQueueNode(QDataType x)
{
    QNode* cur = (QNode*)malloc(sizeof(QNode));
    cur->_data = x;
    cur->_next = NULL;
    return cur;
}
// 初始化队列     
void QueueInit(Queue* q)
{
    q->_front = NULL;
    q->_rear = NULL;
}
// 队尾入队列     
void QueuePush(Queue* q, QDataType data)
{
    QNode* cur = BuyQueueNode(data);
    if (q->_front == NULL)//相当于q._front ==NULL
    {
        q->_front = q->_rear = cur;
    }
    else//有节点就在队列最后尾插,让rear后移一位               
    {
        q->_rear->_next = cur;
        q->_rear = cur;
    }
}
// 队头出队列     
void QueuePop(Queue* q)
{
    assert(q);//出队列就相当于链表的头删一样
    if (q->_front == NULL)
        return;
    QNode* cur = q->_front->_next;
    free(q->_front);
    q->_front = cur;
}
// 获取队列头部元素     
QDataType QueueFront(Queue* q)
{
    return q->_front->_data;
}
// 获取队列队尾元素     
QDataType QueueBack(Queue* q)
{
    return q->_rear->_data;
}
// 获取队列中有效元素个数     
int QueueSize(Queue* q)
{
    QNode* cur;
    int cnt = 0;
    for (cur = q->_front; cur; cur = cur->_next)
    {
        cnt++;
    }
    return cnt;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0     
int QueueEmpty(Queue* q)
{
    if (q->_front == NULL)
        return 1;
    else return 0;
}
// 销毁队列     
void QueueDestroy(Queue* q)
{
    if (q->_front == NULL)
        return;
    while (q->_front)
    {
        QueuePop(q);
    }
}

Queuetest.c

#include"Queue.h"

int main()
{
    Queue q ;
    QueueInit(&q);
    QueuePush(&q, 1);
    QueuePush(&q, 1);
    QueuePush(&q, 1);
    QueuePush(&q, 1);
    QueuePush(&q, 1);
    QueuePush(&q, 1);
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-09-30 01:12:58  更:2022-09-30 01:18:14 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 19:31:24-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码