还是先放这张图,以便对比和理解:

队列是限制在两端进行插入操作和删除操作的线性表,允许进行存入操作的一端称为“队尾”,允许进行删除操作的一端称为“队头”。当线性表中没有元素时,称为“空队”。特点:先进先出(FIFO)。

一、顺序队列
       建立顺序队列结构必须为其静态分配或动态申请一片连续的存储空间,并设置两个指针进行管理。一个是队头指针front,它指向队头元素;另一个是队尾指针rear,它指向下一个入队元素的存储位置,如图所示

每次在队尾插入一个元素是,rear增1;每次哎队头删除一个元素时,front增1。随着插入和删除操作的进行,队列元素的个数不断变化,队列所占的存储空间也在为队列结构所分配的连续空间中移动。当front=rear时,队列中没有任何元素,称为空队列。当rear增加到指向分配的连续空间之外时,队列无法再插入新元素,但这时往往还有大量可用空间未被占用,这些空间是已经出队的队列元素曾经占用过得存储单元。

在实际使用队列时,为了使队列空间能重复使用,往往对队列的使用方法稍加改进:无论插入或删除,一旦rear指针增1或front指针增1 时超出了所分配的队列空间,就让它指向这片连续空间的起始位置。自己真从N(MaxSize)增1变到0,可用取余运算rear%N和front%N来实现。这实际上是把队列空间想象成一个环形空间,环形空间中的存储单元循环使用,用这种方法管理的队列也就称为循环队列

在循环队列中,当队列为空时,有front=rear,而当所有队列空间全占满时,也有front=rear。为了区别这两种情况,规定循环队列最多只能有MaxSize-1个队列元素,当循环队列中只剩下一个空存储单元时,队列就已经满了。因此,队列判空的条件时front=rear,而队列判满的条件时front=(rear+1)%MaxSize。

总结:

1、队头指针front,指向队头元素的位置的前一个位置。即指向预留的位置;

2、队尾指针rear,指向队尾元素的位置;

3、入队: rear = (rear + 1) % N (maxsize),然后元素放入队尾rear所指向的位置;

4、出队: front = (front + 1) % N,然后取出队头指针front所指向的元素;

5、队空: front == rear;

6、队满: (rear + 1) % N == front, N为数组的元素个数;

7、为了区别空队和满队,满队元素个数比数组元素个数少一个。

下面是顺序队列的运算:

顺序队列也是顺序表的一种,具有顺序表同样的存储结构,由数组定义,配合使用数组下表表示的队头指针和队尾完成各种操作:

[cpp] view plaincopy
  1. #define N 64  //队列中数据元素的数据类型
  2. typedef int data_t;
  3. typedef struct
  4. {
  5. data_t data[N]; //用数组作为队列的储存空间
  6. int front,rear; //指示队头位置和队尾位置的指针
  7. }sequeue_t;

1、创建空队列

[cpp] view plaincopy
  1. sequeue_t *CreateEmptySequeue()
  2. {
  3. sequeue_t *queue;
  4. queue = (sequeue_t *)malloc(sizeof(sequeue_t));
  5. if (NULL == queue) return NULL;
  6. queue->front = queue->rear = 0;
  7. return queue;
  8. }

2、摧毁一个队列

[cpp] view plaincopy
  1. void DestroySequeue(sequeue_t *queue)
  2. {
  3. if (NULL != queue)
  4. {
  5. free(queue);
  6. }
  7. }

3、判断一个队列是否为空

[cpp] view plaincopy
  1. int EmptySequeue(sequeue_t *queue)
  2. {
  3. if (NULL == queue)
  4. return -1;
  5. return (queue->front == queue->rear ? 1 : 0);
  6. }

4、判断一个队列是否为满

[cpp] view plaincopy
  1. int FullSequeue(sequeue_t *queue)
  2. {
  3. if (NULL == queue) return -1;
  4. return ((queue->rear + 1) % N == queue->front ? 1 : 0);
  5. }

5、清空一个队列

[cpp] view plaincopy
  1. void ClearSequeue(sequeue_t *queue)
  2. {
  3. if (NULL == queue) return;
  4. queue->front = queue->rear = 0;
  5. return;
  6. }

6、入队

[cpp] view plaincopy
  1. int EnQueue(sequeue_t *queue, data_t x)
  2. {
  3. if (NULL == queue) return - 1;
  4. if (1 == FullSequeue(queue)) return -1; /* full */
  5. queue->rear = (queue->rear + 1) % N;
  6. queue->data[queue->rear] = x;
  7. return 0;
  8. }

7、出队

[cpp] view plaincopy
  1. int DeQueue(sequeue_t *queue, data_t *x)
  2. {
  3. if (NULL == queue) return -1;
  4. if (1 == EmptySequeue(queue)) return -1; /* empty */
  5. queue->front = (queue->front + 1) % N;
  6. if (NULL != x) {
  7. *x = queue->data[queue->front];
  8. }
  9. return 0;
  10. }

二、链式队列

用链表表示的队列简称为链队列,如下图所示


一个链队列显然需要两个分别指示队头和队尾的指针(分别成为头指针和尾指针)才能唯一确定。这里,和线性表的单链表一样,为了操作方便起见,我们也给队列添加一个头结点,并令头指针指向头节点。由此,空的链队列的判决条件为头指针和尾指针均指向头结点,如下图所示:

链队列的操作记为单链表的插入和删除操作的特殊情况,插入操作在队尾进行,删除操作在队头进行,由队头指针和队尾指针控制队列的操作:

[cpp] view plaincopy
  1. typedef int data_t;
  2. typedef struct node_t
  3. {
  4. data_t data;
  5. struct node_t *next;
  6. }linknode_t,*linklist_t;
  7. typedef struct
  8. {
  9. linklist_t front,rear;
  10. }linkqueue_t;

1、创建空队列

[cpp] view plaincopy
  1. linkqueue_t *CreateEmptyLinkqueue()
  2. {
  3. linkqueue_t *lp = (linkqueue_t *)malloc(sizeof(linkqueue_t));
  4. if(lp == NULL)
  5. return;
  6. lp->front = lp->rear = (linknode_t *)malloc(sizeof(linknode_t));
  7. if(lp->front == NULL)
  8. return;
  9. lp->front->next = NULL;
  10. return lp;
  11. }

2、摧毁一个链队列

[cpp] view plaincopy
  1. void DestroyLinkqueue(linkqueue_t *queue)
  2. {
  3. if(queue != NULL)
  4. {
  5. ClearLinkqueue(queue);
  6. free(queue);
  7. }
  8. }

3、清空一个链队列

[cpp] view plaincopy
  1. void ClearLinkqueue(linkqueue_t *queue)
  2. {
  3. linknode_t *qnode;
  4. while(q->front)
  5. {
  6. qnode = queue->front;
  7. queue->front= qnode->next;
  8. free(qnode);
  9. }
  10. queue->rear = NULL;}

4、判断链队列为空

[cpp] view plaincopy
  1. int EmptyLinkqueue(linkqueue_t *queue)
  2. {
  3. if(queue == NULL)
  4. return -1;
  5. return(queue->front == queue->rear ? 1 : 0);
  6. }

5、入队

[cpp] view plaincopy
  1. int EnQueue(linkqueue_t *queue,data_t x)
  2. {
  3. linknode_t *node_new;
  4. if(queue == NULL)
  5. return -1;
  6. node_new = (linknode_t *)malloc(sizeof(linknode_t));
  7. if(node_new == NULL)
  8. return -1;
  9. node_new->data = x;
  10. node_new->next = NULL;
  11. if(queue->front->next == NULL)
  12. {
  13. queue->front->next = queue->rear = node_new;
  14. }
  15. else
  16. {
  17. queue->rear->next = node_new;
  18. queue->rear = node_new;
  19. }
  20. return 0;
  21. }

6、出队

[cpp] view plaincopy
  1. int DeQueue(linkqueue_t *queue,data_t *x)
  2. {
  3. linknode_t *node_remove;
  4. if(queue == NULL || queue->front->next == NULL)
  5. return -1;
  6. node_remove = queue->front->next;
  7. queue->front->next = node_remove->next;
  8. if(x != NULL)
  9. *x = node_remove->data;
  10. free(node_remove);
  11. return 0;
  12. }

Linux C 数据结构——队列相关推荐

  1. linux内核数据结构实现--链表、队列和哈希

    C是面向过程的语言,但是linux内核却用C实现了一套面向对象的设计模式,linux内核中处处体现着面向对象的思想. 1. 内核链表和list_entry 1.1 普通链表实现 我们在语法书上学到的链 ...

  2. linux内核的队列实现移植

    linux内核的队列实现移植 [!TOC] 在c编程中有时会使用一些常用的数据结构,如队列.每次都手写一遍有些麻烦,写一个通用的比较好,而内核有实现队列,直接移植出来就好了. 内核的队列实现 内核的队 ...

  3. go移植linux内核书名叫啥,Go语言移植Linux内核数据结构hlist

    hlist(哈希链表)可以通过相应的Hash算法,迅速找到相关的链表Head及节点. 在有些应用场景,比Go标准库提供的list(一种双向链表)更合适. 依照list.h中的源码,我实现了一个Go语言 ...

  4. java 数据结构_Java版-数据结构-队列(数组队列)

    前言 看过笔者前两篇介绍的 Java版数据结构 数组和 栈的盆友,都给予了笔者一致的好评,在这里笔者感谢大家的认可!!! 由于本章介绍的数据结构是 队列,在队列的实现上会基于前面写的 动态数组来实现, ...

  5. 数据结构——队列的C++实现

    数据结构--队列的C++实现 \qquad队列的创建.判断是否为空或者满.入队和出队操作的C++实现. #include<iostream> using namespace std;//1 ...

  6. java 数据队列_Java 数据结构 - 队列

    Java 数据结构 - 队列 我们今天要讲的数据结构是队列,比如 Java 线程池任务就是队列实现的. 1. 什么是队列 和栈一样,队列也是一种操作受限的线性结构.使用队列时,在一端插入元素,而在另一 ...

  7. 数据结构队列代码_代码简介:队列数据结构如何工作

    数据结构队列代码 Here are three stories we published this week that are worth your time: 这是我们本周发布的三个值得您关注的故事 ...

  8. java循环队列_Java版-数据结构-队列(循环队列)

    前情回顾 在上一篇,笔者给大家介绍了数组队列,并且在文末提出了数组队列实现上的劣势,以及带来的性能问题(因为数组队列,在出队的时候,我们往往要将数组中的元素往前挪动一个位置,这个动作的时间复杂度O(n ...

  9. 第七周--数据结构--队列数组

     /*    *第七周--数据结构--队列数组     *Copyright (c) 2015 烟台大学计算机与控制工程学院    *All right reserved.    *文件名称:li ...

最新文章

  1. 独家 | 手把手教你用Python创建简单的神经网络(附代码)
  2. ES _source字段介绍——json文档,去掉的话无法更新部分文档,最重要的是无法reindex...
  3. python下载的文件放在哪里的-python实现文件下载的方法总结
  4. 面试题——轻松搞定面试中的红黑树问题
  5. k8s Dashboard部署Tomcat集群
  6. 再见 Win10系统!下一代操作系统要来了!!
  7. Vue2.x通用条件搜索组件的封装及应用
  8. 分析方法的基础 — 3. 业务与管理的特性,分析与设计的抓手
  9. python官网无法访问_python写的网站,云服务器经常无法访问
  10. 浏览——用户自定义路径
  11. member selection 运算符是什么
  12. win10+android+手机驱动,win10系统电脑没有手机驱动的解决方法
  13. CCF试题 201903-2 二十四点解析
  14. iOS 苹果登录(第三方登录)
  15. 苹果开发者账号开启双重认证步骤
  16. 2021顺丰科技实习 面经
  17. 我爱我家 - 抗争你们这些黑中介滴致命武器之-要你命1000
  18. 什么是JPA?SpringBoot 中使用JPA
  19. FAERIE QVEENE 仙后节选
  20. java枚举类Enum入门理解

热门文章

  1. C Primer+Plus(十七)高级数据表示 编程练习(二)
  2. 无法加载安装安装程序:Wbemupgd.dll
  3. [見好就收]NET 2.0 - WinForm Control - DataGridView 编程36计
  4. 算法偏见是什么_算法可能会使任何人(包括您)有偏见
  5. 如何使用ArchUnit测试Java项目的体系结构
  6. angular 模块构建_通过构建全栈应用程序学习Angular 6
  7. 这三种策略可以帮助女性在科技领域蓬勃发展
  8. web项目开发人员配比_我如何找到Web开发人员的第一份工作
  9. 外星人图像和外星人太空船_卫星图像:来自太空的见解
  10. MSSQL 发布订阅,实现读写分离