环形队列实现原理 链式实现
队列研究的原理和应用
![队列研究的原理和应用](https://img.taocdn.com/s3/m/59890fc582d049649b6648d7c1c708a1284a0a88.png)
队列研究的原理和应用1. 队列的基本概念队列是一种常见的数据结构,它遵循先进先出(FIFO)的原则。
在队列中,元素按照先后顺序加入队列,而只有最早加入的元素可以被访问和移除。
队列有两个基本操作,即入队(enqueue)和出队(dequeue)。
2. 队列的原理队列可以采用链表或数组来实现。
链表实现的队列使用指针相连的节点来存储元素,每个节点有一个指向下一个节点的指针和一个存储数据的元素。
数组实现的队列则使用连续的存储空间来存储元素,通过两个指针front和rear分别指向队首和队尾。
2.1 队列的入队操作入队操作将元素添加到队尾。
在链表实现中,只需创建一个新节点,并将其插入到队尾节点的后面。
在数组实现中,将元素存储到rear指针所在位置,并将rear指针后移一位。
2.2 队列的出队操作出队操作将队首元素移除。
在链表实现中,只需将队首节点的next指针指向下一个节点,并将原队首节点删除。
在数组实现中,将队首元素移除,并将front指针后移一位。
2.3 队列的空判断和满判断队列是否为空可以通过判断front和rear指针是否相等来进行判断。
如果相等,则队列为空。
队列是否满可以通过判断rear指针的位置是否达到队列的大小来进行判断。
如果rear指针超过了队列的大小,则队列为满。
3. 队列的应用队列在计算机科学和日常生活中有广泛的应用,以下是一些常见的应用场景:3.1 线程池在多线程编程中,线程池用于管理线程的执行顺序。
线程池维护一个固定数量的线程,任务被加入到队列中,每个线程从队列中获取任务并执行。
通过队列来存储任务,可以确保任务按照添加的顺序执行。
3.2 消息队列消息队列用于在分布式系统中传递消息。
生产者将消息发送到消息队列,消费者从消息队列中获取消息并进行处理。
通过消息队列,可以实现不同服务之间的解耦和异步处理。
3.3 操作系统调度在操作系统中,调度算法决定了进程的执行顺序。
队列被用来存储等待执行的进程,根据调度算法的策略,从队列中选择下一个执行的进程。
循环队列是什么结构
![循环队列是什么结构](https://img.taocdn.com/s3/m/1c18433b00f69e3143323968011ca300a6c3f63b.png)
循环队列是什么结构引言:在计算机科学领域中,队列是一种简单而常见的数据结构,它按照先进先出(FIFO)的原则管理数据。
循环队列是队列的一种特殊形式,将队列的首尾连接起来,形成一个环。
本文将详细介绍循环队列的定义、实现和应用。
一、循环队列的定义循环队列是一种通过环形缓冲区实现的线性数据结构,具有固定大小。
它包含一个数组,用于存储数据元素,以及两个指针front和rear,分别指向队列的头部和尾部。
特点:1. 队列为空时,front和rear指向同一个位置;2. 队列满时,front和rear指向相邻位置;3. 队列长度为数组的长度减1。
二、循环队列的实现1. 初始化:创建一个空数组,并将front和rear指针初始化为0。
2. 入队操作:将元素插入rear指针指向的位置,然后将rear指针右移一位。
如果rear指针超过数组边界,则将rear指针重置为0。
3. 出队操作:将front指针指向的元素返回,并将front指针右移一位。
如果front指针超过数组边界,则将front指针重置为0。
4. 队列判空:如果front和rear指向同一个位置,则队列为空。
5. 队列判满:如果rear指针的下一个位置是front指针,则队列为满。
三、循环队列的优势相比于普通队列,循环队列具有以下几个优势:1. 优化了空间利用:循环队列通过环形缓冲区的方式实现,充分利用了数据存储空间,避免了普通队列数组一旦填满就无法再存入元素的问题。
2. 提高了入队和出队的效率:循环队列通过指针的移动实现元素的插入和删除,无需移动整个队列,并且时间复杂度为O(1),相比于普通队列的O(n)效率更高。
3. 简化了队列的操作:循环队列可以自动调整指针的位置,无需移动整个队列,更加简洁高效。
四、循环队列的应用循环队列在实际应用中具有广泛的用途,下面列举了其中几个常见的应用场景:1. 生产者消费者模型:循环队列可以用来实现线程间的数据传递,生产者线程将数据入队,消费者线程从队列中取出数据进行处理。
队列的介绍和利用环形队列实现STM32进阶之串口环形缓冲区的概述
![队列的介绍和利用环形队列实现STM32进阶之串口环形缓冲区的概述](https://img.taocdn.com/s3/m/5792f2612b160b4e767fcfff.png)
队列的介绍和利用环形队列实现STM32进阶之串口环形缓冲区的概述队列的概念
在此之前,我们来回顾一下队列的基本概念:队列(Queue):是一种先进先出(First In First Out ,简称FIFO)的线性表,只允许在一端插入(入队),在另一端进行删除(出队)。
队列的特点
类似售票排队窗口,先到的人看到能先买到票,然后先走,后来的人只能后买到票
队列的常见两种形式
普通队列
在计算机中,每个信息都是存储在存储单元中的,比喻一下吧,上图的一些小正方形格子就是一个个存储单元,你可以理解为常见的数组,存放我们一个个的信息。
当有大量数据的时候,我们不能存储所有的数据,那么计算机处理数据的时候,只能先处理先来的,那么处理完后呢,就会把数据释放掉,再处理下一个。
那么,已经处理的数据的内存就会被浪费掉。
因为后来的数据只能往后排队,如过要将剩余的数据都往前移动一次,那么效率就会低下了,肯定不现实,所以,环形队列就出现了。
环形队列
它的队列就是一个环,它避免了普通队列的缺点,就是有点难理解而已,其实它就是一个队列,一样有队列头,队列尾,一样是先进先出(FIFO)。
我们采用顺时针的方式来对队列进行排序。
队列头 (Head) :允许进行删除的一端称为队首。
队列尾 (Tail) :允许进行插入的一端称为队尾。
环形队列的实现:在计算机中,也是没有环形的内存的,只不过是我们将顺序的内存处理。
图解Java数据结构之环形链表
![图解Java数据结构之环形链表](https://img.taocdn.com/s3/m/f4cb461bf08583d049649b6648d7c1c709a10b56.png)
图解Java数据结构之环形链表本篇⽂章介绍数据结构中的环形链表。
介绍环形链表,类似于单链表,也是⼀种链式存储结构,环形链表由单链表演化过来。
单链表的最后⼀个结点的链域指向NULL,⽽环形链表的建⽴,不要专门的头结点,让最后⼀个结点的链域指向链表结点。
简单点说链表⾸位相连,组成环状数据结构。
如下图结构:⽽在环形链表中,最为著名的即是约瑟夫环问题。
约瑟夫环问题问题介绍:设编号为1、2、3、... 、n的n个⼈围坐⼀圈,约定编号为k(1<=k<=n)的⼈从1开始报数,数到m的那个⼈出列,它的下⼀位⼜从1开始报数,数到m的那个⼈⼜出列。
依次类推,直到所有⼈出列为⽌,由此产⽣⼀个出队编号的序列。
我们可以举个例⼦来分析⼀下:假设⼀共有5个⼈,即n = 5;从第⼀个⼈开始报数,即k = 1;数到2的⼈出列,即m = 2。
⽰意图如下:出队列的顺序即为:2 -> 4 -> 1 -> 5 -> 3那么我们⾸先得构建出⼀个单向的环形链表。
实现分析:1. 先创建第⼀个节点,让first指向该节点,并形成环状2. 每创建⼀个新的节点就将该节点加⼊到已有的环形链表中分析完毕,我们⽤代码实现⼀下://创建⼀个环形的单向链表class CircleSingleLinkedList {// 创建⼀个first节点,当前没有编号private Boy first = null;// 添加节点,构建成⼀个环形链表System.out.println("数据错误");return;}// 定义辅助节点Boy curBoy = null;// 使⽤循环创建环形链表for (int i = 1; i <= nums; i++) {// 根据编号创建节点Boy boy = new Boy(i);// 如果是第⼀个节点if (i == 1) {first = boy;first.setNext(first);curBoy = first;// 让curBoy指向第⼀个节点,帮助构建链表} else {curBoy.setNext(boy);boy.setNext(first);// 使其指向第⼀个节点,形成环状curBoy = boy;// curBoy后移}}}// 遍历当前环形链表public void list() {// 判断链表是否空if (first == null) {System.out.println("链表为空");return;}// 定义辅助节点Boy curBoy = first;while (true) {System.out.println("节点编号:" + curBoy.getNo());if (curBoy.getNext() == first) {// 此时说明遍历完毕break;}curBoy = curBoy.getNext();// curBoy后移}}}//创建⼀个Boy类,表⽰⼀个节点class Boy {private int no;// 编号private Boy next;// 指向下⼀个节点public Boy(int no) {this.no = no;}public int getNo() {return no;}public void setNo(int no) {this.no = no;}public Boy getNext() {return next;}public void setNext(Boy next) {this.next = next;}}这样就实现了⼀个环形链表,接下来测试⼀下:public static void main(String[] args) {CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList(); circleSingleLinkedList.addBoy(5);circleSingleLinkedList.list();}运⾏结果:节点编号:1运⾏结果也是没有问题的,接下来便是⽣成出圈序列。
无锁队列 原理
![无锁队列 原理](https://img.taocdn.com/s3/m/e87a32d59a89680203d8ce2f0066f5335b816744.png)
无锁队列原理无锁队列是指在多线程环境中,使用非阻塞算法实现的一种队列数据结构。
传统的队列实现方式是使用锁来控制并发访问,但是锁的使用对于高并发环境下的性能会有很大的影响。
无锁队列则通过使用一些高效的算法,避免了锁的使用,从而提高了并发性。
无锁队列的实现主要依赖于CPU的原子操作指令,也就是可以一条指令完成的操作。
这些指令能够保证操作的原子性,而不需要使用锁来保证并发访问的正确性。
常见的原子操作指令包括CAS、FAA、FAS等。
在无锁队列中,这些指令主要用于实现队列的插入和删除操作。
无锁队列的实现可以分为两种基本类型:链表实现和环形缓存实现。
链表实现的无锁队列链表实现的无锁队列的基本思路是,通过CAS指令,将待插入的节点插入到队尾。
每个节点包含了一个指向下一个节点的指针。
对于删除操作,通过CAS操作,将头节点的指针指向下一个节点,这样就完成了删除操作。
如果CAS操作失败,则需要重新进行访问,直到成功。
链表实现的无锁队列一般比较适合多生产者单消费者模式。
因为多个线程同时往队列中添加节点时,可能发生ABA问题。
也就是说,一个线程将节点A插入到队列尾部之后,又将节点A删除,并插入节点B。
此时,另一个线程对头节点进行CAS操作,发现头节点的值与自己之前读取的值相等,于是进行了删除操作。
但是这个节点已经被另一个线程删除,这就产生了ABA问题。
针对这个问题,一种解决方案是使用带有时间戳的CAS指令,即每个节点都拥有一个唯一的递增时间戳,通过比较时间戳来判断节点是否被修改,这样可以避免ABA问题的发生。
环形缓存实现的无锁队列的基本思路是,使用一个数组来作为队列的存储空间。
数组具有固定的大小,并且环形地连接起来。
用两个指针(front和rear)来分别表示队列头部和尾部的位置。
对于插入操作,需要将数据存储到队列尾部,并且移动rear指针;对于删除操作,需要将数据从队列头部读取,并且移动front指针。
由于在无锁队列中,多个线程可能会同时修改rear指针和front指针,因此需要使用原子操作指令来保证并发操作的正确性。
队列研究的基本原理
![队列研究的基本原理](https://img.taocdn.com/s3/m/e59e4e15182e453610661ed9ad51f01dc28157a1.png)
队列研究的基本原理队列是一种非常重要的数据结构,其基本原理是“先进先出”,即先加入队列的元素先被取出。
队列在计算机科学中被广泛应用,例如操作系统中的进程调度、网络数据包传输等等。
本文将介绍队列的基本原理、应用场景以及常见的队列实现方式。
一、队列的基本原理队列是一种线性数据结构,可以看成是特殊的线性表。
队列的基本操作包括入队和出队。
入队是在队列的尾部添加一个元素,出队是从队列的头部删除一个元素。
由于队列是先进先出的,因此每次出队操作总是删除队列中最早被加入的元素。
队列的头部和尾部分别称为队头和队尾,队头是队列中最早加入的元素,队尾是队列中最后加入的元素。
队列的实现有多种方式,最常见的是使用数组或链表来实现。
使用数组实现队列时,需要定义一个数组来存储队列中的元素,同时使用两个指针front和rear分别指向队列的头部和尾部。
入队操作时,将元素添加到rear指向的位置,同时将rear指针向后移动一位;出队操作时,将front指针向后移动一位,同时删除队头元素。
当front等于rear时,队列为空。
使用链表实现队列时,每个节点包含一个元素和一个指向下一个节点的指针。
使用两个指针front和rear分别指向队列的头部和尾部节点。
入队操作时,新建一个节点并将其添加到rear指向的节点后面,同时将rear指针指向新节点;出队操作时,删除front指向的节点,同时将front指针指向下一个节点。
当front等于rear时,队列为空。
二、队列的应用场景队列在计算机科学中有广泛的应用场景,下面列举几个常见的例子。
1. 操作系统中的进程调度在操作系统中,进程是指正在运行的程序的实例。
操作系统需要管理多个进程的运行,因此需要进行进程调度。
操作系统使用队列来管理进程,将所有等待运行的进程加入到一个队列中,依次从队列中取出进程进行运行。
当一个进程运行结束或等待某些资源时,将其重新加入到队列中等待运行。
2. 网络数据包传输在网络中,数据包是网络传输的基本单位。
环行队列的知识点总结
![环行队列的知识点总结](https://img.taocdn.com/s3/m/8fd2714ba7c30c22590102020740be1e640ecc4b.png)
环行队列的知识点总结一、环形队列的定义环形队列是一种特殊的队列,它采用循环数组的方式来实现。
环形队列和普通队列相比,能够更好地利用内存空间,减少内存的浪费。
二、环形队列的特点1. 采用循环数组存储数据,解决了普通队列在入队出队操作中浪费内存空间的问题;2. 使用两个指针来标识队头和队尾,实现循环队列的功能;3. 环形队列的长度固定,当队列满时,无法插入新的元素;4. 环形队列的插入和删除操作都具有较高的效率。
三、环形队列的基本操作1. 初始化:创建一个具有固定大小的环形队列,并初始化队头和队尾指针。
2. 入队操作:向队尾指针所指向的位置插入一个新的元素,并更新队尾指针。
3. 出队操作:删除队头指针所指向的元素,并更新队头指针。
4. 判空操作:当队列为空时,队头指针和队尾指针相等。
5. 判满操作:当队列满时,队尾指针的下一个位置等于队头指针。
四、环形队列的实现1. 环形队列可以采用数组来实现,同时需要两个指针来标识队头和队尾。
2. 入队操作:判断队列是否满,若满则无法插入新元素;若不满,则将新元素加入到队尾,并更新队尾指针。
3. 出队操作:判断队列是否空,若空则无法删除元素;若非空,则删除队头元素,并更新队头指针。
4. 注意循环数组的处理,当队尾指针到达数组的末尾时,需要将其指向数组的起始位置。
五、环形队列的应用1. 缓冲区:环形队列可以用于实现缓冲区,存储需要处理的数据。
2. 消息队列:在系统中,环形队列可以用作消息队列,实现进程间的通信。
3. 循环播放:在媒体播放器中,可以使用环形队列来实现音乐或视频的循环播放功能。
4. CPU调度:操作系统中可以使用环形队列来实现CPU的任务调度。
六、环形队列的优缺点1. 优点:能够更好地利用内存空间,减少内存的浪费;具有较高的效率和性能;2. 缺点:长度固定,无法动态扩展;插入和删除操作需要维护两个指针,实现稍复杂。
七、环形队列的应用场景1. 需要高效的队列数据结构;2. 内存空间有限,需要更好地利用内存;3. 需要循环存储数据的场合。
jctools 队列原理
![jctools 队列原理](https://img.taocdn.com/s3/m/500cce30ba68a98271fe910ef12d2af90342a87a.png)
jctools 队列原理JCTools队列原理简介JCTools是一个开源的Java并发编程工具包,它提供了一系列高效的数据结构和算法,用于解决多线程环境下的并发问题。
其中,JCTools队列是其核心组件之一,在并发编程中具有重要的作用。
什么是JCTools队列JCTools队列是一种基于无锁算法的并发队列实现,它通过避免使用锁来提高并发性能。
相比于传统的阻塞队列,JCTools队列在高并发场景下具有更好的性能和可伸缩性。
队列的基本原理1.无锁算法:JCTools队列采用无锁算法实现,避免了使用锁的开销和竞争。
无锁算法通过使用原子操作和CAS(Compare andSwap)指令来保证多线程之间的数据一致性。
2.环形缓冲区:JCTools队列内部使用一个环形缓冲区作为底层数据结构。
该缓冲区由固定大小的数组构成,通过循环计数器来实现环形的特性。
3.多生产者-多消费者模型:JCTools队列支持多个生产者和多个消费者并发操作。
它通过一些高效的并发逻辑,确保生产者和消费者之间的数据操作是安全的,不会出现数据丢失或覆盖的问题。
JCTools队列的特性•高并发性能:JCTools队列通过使用无锁算法和环形缓冲区,可以支持大量线程的高并发操作,提供出色的性能表现。
•可伸缩性:JCTools队列在多生产者-多消费者模型下,能够很好地适应不同线程数的并发需求,具有良好的可伸缩性。
•内存友好:JCTools队列在设计时考虑了内存分配和回收的效率,并且避免了不必要的内存开销,提供了更好的内存友好性。
•灵活性:JCTools队列提供不同类型的队列实现,例如单生产者-单消费者队列、多生产者-单消费者队列和多生产者-多消费者队列等,以满足不同场景下的需求。
使用JCTools队列的注意事项1.适当选择队列类型:根据实际情况选择适合的队列类型,避免过度设计或低效率的使用。
2.合理设置队列容量:根据业务需求设置合理的队列容量,避免队列溢出或造成过多的内存开销。
循环队列push_back实现原理
![循环队列push_back实现原理](https://img.taocdn.com/s3/m/6e80f31d2e60ddccda38376baf1ffc4fff47e241.png)
循环队列push_back实现原理循环队列是一种经典的数据结构,它可以实现高效的队列操作。
在循环队列中,我们可以使用push_back操作来向队列尾部插入新的元素。
本文将介绍循环队列的原理,并详细解释push_back操作的实现过程。
一、循环队列的概念和原理循环队列是一种环形的数据结构,它的底层是一个数组。
循环队列的特点是,当队列的尾部指针指向数组的最后一个位置时,如果队列仍有空闲空间,那么新的元素将被插入到数组的第一个位置,形成一个循环。
这样一来,我们就可以循环利用数组的空间,避免了数组中元素的搬移操作。
循环队列通常由两个指针来表示,一个是队头指针front,一个是队尾指针rear。
初始时,它们都指向数组的第一个位置。
队列中的元素从队头指针的位置开始,依次向后排列,直到队尾指针的位置。
当队列为空时,front和rear指针相等,当队列满时,rear指针指向的位置是front指针的前一个位置。
二、push_back操作的实现过程push_back操作是向循环队列的尾部插入新的元素。
它的具体实现过程如下:1. 首先,判断队列是否已满。
如果队列已满,即rear指针的下一个位置是front指针的位置,表示队列已满,无法插入新的元素。
在这种情况下,我们可以选择两种处理方式:一种是抛出异常,通知调用者队列已满;另一种是自动扩容,重新分配更大的数组空间。
这里我们选择抛出异常的方式。
2. 如果队列未满,将新的元素插入到rear指针的位置,并将rear 指针后移一位。
具体操作如下:(1)将新的元素赋值给rear指针指向的位置:queue[rear] = element;(2)将rear指针后移一位:rear = (rear + 1) % queueSize;这里使用取模运算来实现循环。
3. 返回插入成功的提示信息。
三、总结本文介绍了循环队列的概念和原理,并详细解释了push_back操作的实现过程。
循环队列通过循环利用数组的空间,实现了高效的队列操作。
队列研究的原理应用是什么
![队列研究的原理应用是什么](https://img.taocdn.com/s3/m/b25d930f777f5acfa1c7aa00b52acfc789eb9fdc.png)
队列研究的原理应用是什么一、队列的基本原理队列是一种先进先出(First In First Out,FIFO)的数据结构,其中插入(enqueue)操作发生在队列的一端,称为队尾(rear),删除(dequeue)操作发生在队列的另一端,称为队头(front)。
二、队列的应用领域队列的原理在计算机科学领域有着广泛的应用。
以下是队列原理几个主要的应用领域:1.作业调度:操作系统通过队列管理系统的任务调度,按照作业的先后顺序进行执行,保证公平性和效率。
2.网络通信:在TCP/IP协议中,网络数据包的传输依赖于队列,通过排队等待发送,确保数据的有序性和可靠性。
3.并发编程:在多线程编程中,队列可以作为线程间通信的一种方式,实现数据共享和同步控制。
4.缓冲区管理:队列可以用于缓冲区管理,用于存储和转发数据。
比如视频流的缓冲,实现流畅的播放。
5.任务队列:在操作系统和应用程序中,任务队列是常用的一种组织方式,用于管理需要被执行的任务。
6.消息队列:消息队列是分布式系统中常用的一种通信方式,用于实现不同组件之间的数据传递和解耦。
三、队列的实现方式队列可以使用不同的数据结构来实现,常见的有数组和链表两种方式。
1.数组实现:使用数组来存储队列元素,通过维护队头和队尾指针来实现插入和删除操作。
数组实现的队列具有固定的容量,需要注意队列满和队列空的判断。
2.链表实现:使用链表来存储队列元素,通过维护链表的头尾指针来实现插入和删除操作。
链表实现的队列没有固定容量的限制,但需要额外的空间来存储指针。
四、队列的基本操作队列的基本操作包括插入(enqueue)、删除(dequeue)和获取队头元素(getFront)等。
1.插入(enqueue)操作:将元素添加到队列的尾部。
如果队列已满,则插入操作会失败。
2.删除(dequeue)操作:删除队头的元素,并返回其值。
如果队列为空,则删除操作会失败。
3.获取队头元素(getFront)操作:返回队头的元素值,但不删除。
实现环形队列的各种基本运算的算法
![实现环形队列的各种基本运算的算法](https://img.taocdn.com/s3/m/b15a4762580102020740be1e650e52ea5518ce88.png)
实现环形队列的各种基本运算的算法一、引言环形队列是一种特殊的队列数据结构,它的特点是首尾相连,形成一个环形的结构。
在环形队列中,插入和删除操作可以在常数时间内完成,因此在实际应用中被广泛使用。
本文将介绍如何实现环形队列的各种基本运算的算法,包括初始化、入队、出队、判空、判满等操作。
二、初始化环形队列初始化环形队列需要创建一个固定大小的数组来存储队列中的元素,并设置头尾指针。
首先,我们需要定义一个变量n来表示队列的大小,然后创建一个大小为n的数组来存储元素。
接着,我们定义两个指针front和rear来分别指向队列的头部和尾部。
初始化时,我们将front和rear都设置为0,表示队列为空。
三、入队操作入队操作将一个元素插入到队列的尾部。
首先,我们需要判断队列是否已满,如果rear+1等于front,则表示队列已满,无法插入新元素。
否则,我们将新元素插入到rear所指向的位置,并将rear 指针后移一位。
如果rear已经指向了队列的末尾,我们需要将rear 重置为0,以实现环形结构。
四、出队操作出队操作将队列头部的元素删除,并将头部指针front后移一位。
首先,我们需要判断队列是否为空,如果front等于rear,则表示队列为空,无法进行出队操作。
否则,我们将front指针后移一位,并返回front指针所指向的元素。
如果front已经指向了队列的末尾,我们需要将front重置为0,以实现环形结构。
五、判空操作判空操作用于判断队列是否为空。
如果front等于rear,则表示队列为空,否则队列不为空。
六、判满操作判满操作用于判断队列是否已满。
如果rear+1等于front,则表示队列已满,否则队列未满。
七、算法实现下面是环形队列的算法实现:1. 初始化环形队列- 定义变量n表示队列大小- 创建大小为n的数组queue- 定义指针front和rear,并将它们都初始化为02. 入队操作- 判断队列是否已满- 如果队列已满,则返回错误信息- 否则,将新元素插入到rear所指向的位置- 将rear后移一位,并判断rear是否已经到达队列末尾,如果是则将rear重置为03. 出队操作- 判断队列是否为空- 如果队列为空,则返回错误信息- 否则,将front后移一位,并返回front指向的元素- 判断front是否已经到达队列末尾,如果是则将front重置为04. 判空操作- 如果front等于rear,则返回true,表示队列为空- 否则,返回false,表示队列不为空5. 判满操作- 如果rear+1等于front,则返回true,表示队列已满- 否则,返回false,表示队列未满八、总结本文介绍了如何实现环形队列的各种基本运算的算法,包括初始化、入队、出队、判空、判满等操作。
循环队列之约瑟夫环问题
![循环队列之约瑟夫环问题](https://img.taocdn.com/s3/m/c96d8e0c17fc700abb68a98271fe910ef12dae37.png)
循环队列之约瑟夫环问题约瑟夫问题 约瑟夫环(约瑟夫问题)是⼀个数学的应⽤问题:已知n个⼈(以编号1,2,3...n分别表⽰)围坐在⼀张圆桌周围。
从编号为k的⼈开始报数,数到m的那个⼈出列;他的下⼀个⼈⼜从1开始报数,数到m的那个⼈⼜出列;依此规律重复下去,直到圆桌周围的⼈全部出列。
通常解决这类问题时我们把编号从0~n-1,最后结果+1即为原问题的解。
循环队列求解(链式)#include<stdio.h>#include<stdlib.h>//循环队列//typedef int ElemType;typedef struct QueueNode{int data;struct QueueNode *next;}QueueNode;typedef struct Queue{QueueNode *front;QueueNode *rear;}Queue;void InitQueue(Queue *q){q->front=q->rear=NULL;}void EnQueue(Queue *q , int value){QueueNode *temp=(QueueNode*)malloc(sizeof(QueueNode));temp->data=value;if(q->rear==NULL){temp->next=temp;q->rear=q->front=temp;}else{temp->next=q->rear->next;q->rear->next=temp;q->rear=temp;}}//enter a element from the tailvoid DeQueue(Queue *q, int *value){QueueNode *temp=(QueueNode*)malloc(sizeof(QueueNode)); if(q->rear==NULL){return;}// It's nullelse if(q->rear->next==q->rear){*value=q->front->data;free(q->rear);q->rear=q->front=NULL;}//It just has one nodeelse{*value=q->front->data;temp=q->front;q->front=temp->next;q->rear->next=q->front;}//more one nodefree(temp);}//delete a element from the headint main(){Queue *q=(Queue*)malloc(sizeof(Queue));int i,m,n,count,temp;printf("请输⼊⼈数n和循环要报的数m(两数之间留个空格)\n"); scanf("%d%d",&n,&m);for(i=1;i<=n;i++)EnQueue(q,i);printf("出圈序列:\n");while(q->front){ count=1;while(count<m){q->front=q->front->next;q->rear=q->rear->next;count++;}count=1;DeQueue(q,&temp);printf("%d ",temp);}putchar('\n');}简单解法#include <stdio.h>int josephus(int n, int m) {if(n == 1) {return0;}else {return (josephus(n-1, m) + m) % n;}}int main() {int n, m;while (scanf("%d", &n) == 1) {if (!n) {break;}scanf("%d", &m);int result = josephus(n, m);printf("%d\n", result+1);}return0;}。
数据结构:循环队列(C语言实现)
![数据结构:循环队列(C语言实现)](https://img.taocdn.com/s3/m/2b2b29bbcf84b9d529ea7a21.png)
数据结构:循环队列(C语言实现)生活中有很多队列的影子,比如打饭排队,买火车票排队问题等,可以说与时间相关的问题,一般都会涉及到队列问题;从生活中,可以抽象出队列的概念,队列就是一个能够实现“先进先出”的存储结构。
队列分为链式队列和静态队列;静态队列一般用数组来实现,但此时的队列必须是循环队列,否则会造成巨大的内存浪费;链式队列是用链表来实现队列的。
这里讲的是循环队列,首先我们必须明白下面几个问题一、循环队列的基础知识1.循环队列需要几个参数来确定循环队列需要2个参数,front和rear2.循环队列各个参数的含义(1)队列初始化时,front和rear值都为零;(2)当队列不为空时,front指向队列的第一个元素,rear指向队列最后一个元素的下一个位置;(3)当队列为空时,front与rear的值相等,但不一定为零;3.循环队列入队的伪算法(1)把值存在rear所在的位置;(2)rear=(rear+1)%maxsize ,其中maxsize代表数组的长度;程序代码:[cpp]view plaincopy1.bool Enqueue(PQUEUE Q, int val)2.{3.if(FullQueue(Q))4.return false;5.else6. {7. Q->pBase[Q->rear]=val;8. Q->rear=(Q->rear+1)%Q->maxsize;9.return true;10. }11.}4.循环队列出队的伪算法(1)先保存出队的值;(2)front=(front+1)%maxsize ,其中maxsize代表数组的长度;程序代码:[cpp]view plaincopy1.bool Dequeue(PQUEUE Q, int *val)2.{3.if(EmptyQueue(Q))4. {5.return false;6. }7.else8. {9. *val=Q->pBase[Q->front];10. Q->front=(Q->front+1)%Q->maxsize;11.return true;12. }13.}5.如何判断循环队列是否为空if(front==rear)队列空;else队列不空;[cpp]view plaincopy1.bool EmptyQueue(PQUEUE Q)2.{3.if(Q->front==Q->rear) //判断是否为空4.return true;5.else6.return false;7.}6.如何判断循环队列是否为满这个问题比较复杂,假设数组的存数空间为7,此时已经存放1,a,5,7,22,90六个元素了,如果在往数组中添加一个元素,则rear=front;此时,队列满与队列空的判断条件front=rear相同,这样的话我们就不能判断队列到底是空还是满了;解决这个问题有两个办法:一是增加一个参数,用来记录数组中当前元素的个数;第二个办法是,少用一个存储空间,也就是数组的最后一个存数空间不用,当(rear+1)%maxsiz=front时,队列满;[cpp]view plaincopy1.bool FullQueue(PQUEUE Q)2.{3.if(Q->front==(Q->rear+1)%Q->maxsize) //判断循环链表是否满,留一个预留空间不用4.return true;5.else6.return false;7.}附录:queue.h文件代码:[cpp]view plaincopy1.#ifndef __QUEUE_H_2.#define __QUEUE_H_3.typedef struct queue4.{5.int *pBase;6.int front; //指向队列第一个元素7.int rear; //指向队列最后一个元素的下一个元素8.int maxsize; //循环队列的最大存储空间9.}QUEUE,*PQUEUE;10.11.void CreateQueue(PQUEUE Q,int maxsize);12.void TraverseQueue(PQUEUE Q);13.bool FullQueue(PQUEUE Q);14.bool EmptyQueue(PQUEUE Q);15.bool Enqueue(PQUEUE Q, int val);16.bool Dequeue(PQUEUE Q, int *val);17.#endifqueue.c文件代码:[cpp]view plaincopy1.#include<stdio.h>2.#include<stdlib.h>3.#include"malloc.h"4.#include"queue.h"5./***********************************************6.Function: Create a empty stack;7.************************************************/8.void CreateQueue(PQUEUE Q,int maxsize)9.{10. Q->pBase=(int *)malloc(sizeof(int)*maxsize);11.if(NULL==Q->pBase)12. {13. printf("Memory allocation failure");14. exit(-1); //退出程序15. }16. Q->front=0; //初始化参数17. Q->rear=0;18. Q->maxsize=maxsize;19.}20./***********************************************21.Function: Print the stack element;22.************************************************/23.void TraverseQueue(PQUEUE Q)24.{25.int i=Q->front;26. printf("队中的元素是:\n");27.while(i%Q->maxsize!=Q->rear)28. {29. printf("%d ",Q->pBase[i]);30. i++;31. }32. printf("\n");33.}34.bool FullQueue(PQUEUE Q)35.{36.if(Q->front==(Q->rear+1)%Q->maxsize) //判断循环链表是否满,留一个预留空间不用37.return true;38.else39.return false;40.}41.bool EmptyQueue(PQUEUE Q)42.{43.if(Q->front==Q->rear) //判断是否为空44.return true;45.else46.return false;47.}48.bool Enqueue(PQUEUE Q, int val)49.{50.if(FullQueue(Q))51.return false;52.else53. {54. Q->pBase[Q->rear]=val;55. Q->rear=(Q->rear+1)%Q->maxsize;56.return true;57. }58.}59.60.bool Dequeue(PQUEUE Q, int *val)61.{62.if(EmptyQueue(Q))63. {64.return false;65. }66.else67. {68. *val=Q->pBase[Q->front];69. Q->front=(Q->front+1)%Q->maxsize;70.return true;71. }72.}[文档可能无法思考全面,请浏览后下载,另外祝您生活愉快,工作顺利,万事如意!]。
实现循环队列上各种基本运算的算法
![实现循环队列上各种基本运算的算法](https://img.taocdn.com/s3/m/526aae46a7c30c22590102020740be1e650ecced.png)
实现循环队列上各种基本运算的算法循环队列是一种特殊的队列,它的底层实现是通过数组来存储数据,并通过两个指针(front指针和rear指针)来确定队头和队尾的位置。
循环队列的特点是:队满和队空的判定条件相同,即队头指针与队尾指针相邻时,队列为满;队头指针与队尾指针相等时,队列为空。
循环队列的基本运算包括:初始化队列、入队操作、出队操作、获取队头元素、获取队列长度、判定队空和队满。
1. 初始化队列初始化循环队列需要创建一个指定大小的数组,并将前后指针(front和rear)都指向数组的起始位置。
代码如下:```pythondef init_queue(size):return [None] * size, 0, 0```2. 入队操作入队操作主要涉及向队尾添加元素,并同时更新rear指针。
如果队列已满,则无法添加元素。
代码如下:```pythondef enqueue(queue, item):size, front, rear = queueif (rear + 1) % size == front:print("Queue is full")queue[rear] = itemqueue[2] = (rear + 1) % size```3. 出队操作出队操作主要涉及从队头移除元素,并同时更新front指针。
如果队列为空,则无法进行出队操作。
代码如下:```pythondef dequeue(queue):size, front, rear = queueif front == rear:print("Queue is empty")else:item = queue[front]queue[front] = Nonequeue[1] = (front + 1) % sizereturn item```4. 获取队头元素获取队头元素操作是指返回队列中第一个元素的值,但不移除元素。
队列研究的原理及类型
![队列研究的原理及类型](https://img.taocdn.com/s3/m/4f23b5b49f3143323968011ca300a6c30c22f1c4.png)
队列研究的原理及类型队列(Queue)是一种常用的数据结构,它按照先进先出(First-In-First-Out,FIFO)的原则进行操作。
在队列中,新元素插入的一端称为队尾(rear),已有元素删除的一端称为队头(front)。
队列在计算机科学中有着广泛的应用,例如任务调度、消息传递、缓冲区管理等。
队列的原理:队列的主要操作有入队(enqueue)和出队(dequeue)操作。
当一个元素入队时,它被添加到队列的队尾;当一个元素出队时,它从队列的队头被删除。
由于队列的FIFO原则,元素在出队时,必须是最早进入队列的元素,也就是队列中存在时间最长的元素。
队列的类型:1. 普通队列(Simple Queue):普通队列是最基本的队列类型,它只允许在队尾插入新元素,并且只能在队头删除元素。
普通队列只能按顺序逐个处理队列中的元素,不能插入和删除中间的元素。
2. 双端队列(Double-ended Queue,Deque):双端队列提供了从队头和队尾两端进行插入和删除操作的功能。
双端队列可以在任意一端插入新元素,也可以在任意一端删除元素。
双端队列的灵活性使得它在一些应用场景下比普通队列更加方便。
3. 优先级队列(Priority Queue):优先级队列中的每个元素都有一个与之关联的优先级,优先级最高的元素在队列的最前面。
优先级队列常用于任务调度等场景,可以按照优先级的高低来安排任务的执行顺序。
4. 环形队列(Circular Queue):环形队列是一种特殊的队列,它的队尾和队头相连,形成一个环。
环形队列允许数据在队列的两端循环移动,使得队列可以有效利用存储空间。
环形队列常用于缓冲区管理、循环队列等场景。
队列的应用:队列在计算机科学中有着广泛的应用,包括但不限于以下几个方面:1.任务调度:多线程或多进程系统中,使用队列来安排待执行的任务,保证按照任务的提交顺序逐个执行。
2.缓冲区管理:队列可以作为缓冲区来管理输入输出的数据流,允许缓冲区与输入输出速率不匹配的情况。
队列研究的原理应用有哪些
![队列研究的原理应用有哪些](https://img.taocdn.com/s3/m/268db0b47d1cfad6195f312b3169a4517723e5f6.png)
队列研究的原理应用有哪些简介队列是数据结构中常用的一种形式,它遵循先进先出(First-In, First-Out,FIFO)的原则。
队列的研究和应用涉及到许多领域,包括计算机科学、通信网络、操作系统等。
以下是队列研究原理及其应用的讨论。
研究原理1. 队列基本操作队列的基本操作包括入队(enqueue)和出队(dequeue)。
入队将元素添加到队列的末尾,出队将队头的元素移除。
这些操作可以由数组或链表实现。
2. 队列的实现方式队列的实现方式有多种,常见的有数组队列和链表队列。
数组队列使用固定容量的数组,入队和出队操作在数组的两端进行。
链表队列使用链表结构,入队和出队操作在链表的头尾进行。
3. 队列的性质队列满足先进先出的原则,并且具有固定大小或动态扩展的能力。
队列还可以为空,即没有元素的情况。
4. 队列的应用队列在计算机科学的许多领域有广泛的应用,包括以下几个方面:•操作系统调度在操作系统中,队列被用来调度进程或线程的执行顺序。
通过维护一个就绪队列和等待队列,操作系统可以按照一定的策略选择下一个要执行的进程或线程。
•打印机任务管理队列可以被用来管理打印机的任务。
当多个任务并发提交给打印机时,队列可以保证它们按照提交的顺序依次打印。
•网络数据传输在网络通信中,数据包通常通过队列进行传输。
数据包被添加到发送队列,然后按照顺序发送给接收方,以保证数据的完整性和按序到达。
•消息传递队列可以用作消息传递的一种方式。
发送方将消息放入队列中,接收方从队列中取出消息进行处理。
这种方式可以实现解耦和异步通信。
•图像处理在图像处理中,队列被用来管理待处理的图像任务。
多个处理单元可以从队列中获取任务并进行处理,保证任务的按序执行。
•缓存管理队列可以用作缓存的一种形式。
某些系统中,为了提高数据的访问效率,将数据存储到缓存队列中,从而减少对底层存储的访问次数。
•多线程协作队列可以用作多线程之间的协作工具。
一个线程将任务放入队列,其他线程从队列取出任务并进行处理,实现任务的并发执行。
c语言数据结构(环形队列)
![c语言数据结构(环形队列)](https://img.taocdn.com/s3/m/9ac1123fbfd5b9f3f90f76c66137ee06eef94e4a.png)
c语言数据结构(环形队列)环形队列是一种经典的数据结构,它在很多场景中发挥着重要的作用。
本文将介绍C语言中的环形队列的原理、实现及其在实际应用中的一些注意事项。
1.环形队列的原理环形队列是一种特殊的队列,它的底层数据结构是一个数组。
与普通队列不同的是,当队列的尾指针指向数组的最后一个位置时,如果还需要继续插入元素,尾指针则跳转到数组的第一个位置。
这样就形成了一个环形的结构,可以循环利用数组中的空间。
2.环形队列的实现环形队列的实现主要涉及到以下几个要素:-队列的初始化:需要给队列分配一块固定大小的内存空间,并初始化队列的头指针和尾指针。
-入队操作:将元素插入到队列的尾部,并更新尾指针的位置。
-出队操作:将队列头部的元素移除,并更新头指针的位置。
-判空操作:判断队列是否为空,即头指针和尾指针是否相等。
-判满操作:判断队列是否已满,即尾指针的下一个位置是否等于头指针。
以下是一个基于数组的环形队列的简单实现:```c#define MAX_SIZE 100typedef structint data[MAX_SIZE];int front; // 头指针int rear; // 尾指针} CircularQueue;void initQueue(CircularQueue *queue)queue->front = 0;queue->rear = 0;void enqueue(CircularQueue *queue, int element)if ((queue->rear + 1) % MAX_SIZE == queue->front) printf("Queue is full.\n");return;}queue->data[queue->rear] = element;queue->rear = (queue->rear + 1) % MAX_SIZE;int dequeue(CircularQueue *queue)if (queue->front == queue->rear)printf("Queue is empty.\n");return -1;}int element = queue->data[queue->front];queue->front = (queue->front + 1) % MAX_SIZE;return element;int isEmpty(CircularQueue *queue)return queue->front == queue->rear;int isFull(CircularQueue *queue)return (queue->rear + 1) % MAX_SIZE == queue->front;```3.环形队列的应用注意事项在使用环形队列时,需要注意以下几点:-队列的大小是有限制的,如果插入元素的速度过快,可能会导致队列溢出。
Java环形队列框架Disruptor的机械共鸣设计理念
![Java环形队列框架Disruptor的机械共鸣设计理念](https://img.taocdn.com/s3/m/72668b5fff4733687e21af45b307e87101f6f8db.png)
Java 环形队列框架Disruptor 的机械共鸣设计理念⾼性能环形队列框架 Disruptor"你并不需要先成为⼀个⼯程师才能去做⼀个赛车⼿,但是你得有⼀种机械共鸣 (Mechanical Sympathy)" -- 杰基•斯图尔特机械共鸣理念源⾃赛车⽐赛,只有⾜够了解赛车的机械原理,才能成为更好的赛车⼿。
程序员也是同理,要写出⾼性能的程序,也需要从底层硬件运⾏情况上来考虑上层应⽤的设计,极致挖掘机器的性能。
Disruptor 性能基准测试以下是⼀组官⽅提供的与ArrayBlockQueue 对⽐的性能基准测试Nehalem 2.8Ghz –Windows 7 SP1 64-bit Sandy Bridge 2.2Ghz –Linux 2.6.38 64-bit ABQ Disruptor ABQ DisruptorUnicast: 1P – 1C 5,339,25625,998,3364,057,45322,381,378Pipeline: 1P – 3C 2,128,91816,806,1572,006,90315,857,913Sequencer:3P – 1C 5,539,53113,403,2682,056,11814,540,519Multicast:1P – 3C 1,077,3849,377,871260,73310,860,121Diamond:1P – 3C 2,113,94116,143,6132,082,72515,295,197Disruptor 核⼼组件Sequence可以视为⼀个存储Long 类型的序号包装类,内部提供了对序号的⽆锁读写能⼒,主要⽤于存储当前⽣产游标及消费的消费游标。
RingBuffer 及每⼀个EventHandler 都会利⽤ Sequence 来维护其⽣产或消费的相关位置信息。
Sequencer封装了对ringBuffer ⽣产消费游标的访问算法,例如获取当前所有消费者消费的最⼩游标位置,⽣产者发布事件时基于这个位置来决定当前事件是否会错误覆盖未消费的事件。
队列研究的基本原理
![队列研究的基本原理](https://img.taocdn.com/s3/m/893ef62d793e0912a21614791711cc7931b77831.png)
队列研究的基本原理
队列研究的基本原理是先进先出(First In First Out,简称FIFO)。
队列是一种线性数据结构,其特点是只允许在表的
一端进行插入操作,称为队尾,而在另一端进行删除操作,称为队头。
队列的操作可以分为入队和出队两种操作。
入队操作将元素加入队尾,而出队操作将从队头移除元素。
在队列中,元素是按照先进先出的顺序被处理的,所以当一个元素被插入到队列中后,它会被保留在队列中,直到它成为队列头部元素并被移除。
队列可以用数组或链表实现。
用数组实现的队列被称为顺序队列,而用链表实现的队列被称为链式队列。
队列可以用于解决很多实际问题,比如在计算机系统中处理任务或请求,模拟排队等。
队列的基本原理是先进先出,这使得队列在某些应用场景下非常有用。
例如,在操作系统中,多个进程需要共享一个打印机资源。
此时,打印请求会被按照先后顺序加入到打印队列中,然后按照队列顺序逐个处理。
另一个例子是在计算机网络中,网络数据包需要按照先后顺序传输。
这时候,数据包会按照顺序加入发送队列,然后按照队列顺序一个个发送出去。
队列的基本原理使得其具有一些重要的特性。
首先,队列可以有效地实现任务的调度,按照先后顺序处理任务。
其次,队列可以控制并发访问,防止多个线程同时访问共享数据。
最后,队列的插入和删除操作的时间复杂度是O(1),因此效率较高。
总结来说,队列研究的基本原理是先进先出,这是由队列的特性决定的。
队列可以用于解决许多实际问题,如任务调度、数据传输等,具有重要的应用价值。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
if(ringq_poll(p_queue, &data) >= 0)
PRINT_INT(data);
ringq_free(p_queue);
}
/*测试第一种环形队列,更加复杂的情况*/
void test6()
{
RINGQ rq, * p_queue;
int i, data;
出队操作:如果队列不空,则从head处读出。
下一个可读的位置在q->head = (q->head + 1) % q->size
头文件
ringq.h
#ifndef __RINGQ_H__
#define __RINGQ_H__
#ifdef __cplusplus
extern "C" {
#endif
#define RINGQ_MAX 20
ringq_push(p_queue, 5);
if(ringq_poll(p_queue, &data) >= 0)
PRINT_INT(data);
if(ringq_poll(p_queue, &data) >= 0)
PRINT_INT(data);
ringq_push(p_queue, 6);
if(ringq_poll(p_queue, &data) >= 0)
{
print_ringq(p_queue);
if(ringq_is_empty(p_queue))
{
printf("ringq is empty\n");
return -1;
}
*p_data = p_queue->space[p_queue->head];
p_queue->head = (p_queue->head + 1) % p_queue->size ;
#include "ringq.h"
int ringq_init(RINGQ * p_ringq)
{
p_ringq->size = RINGQ_MAX;
p_ringq->head = 0;
p_ringq->tail = 0;
下一个可读的位置在q->head = (q->head + 1) % q->size
完整代码
头文件ringq.h
#ifndef __RINGQ_H__
#define __RINGQ_H__
#ifdef __cplusplus
extern "C" {
#endif
#define QUEUE_MAX 20
extern int ringq_poll(RINGQ * p_ringq,int * p_data);
#define ringq_is_empty(q) (q->head == q->tail)
#define ringq_is_full(q) (((q->tail+1)%q->size) == q->head )
{
return 0;
}
int ringq_push(RINGQ *p_queue, int data)
{
print_ringq(p_queue);
if(ringq_is_full(p_queue))
{
printf("ringq is full\n");
return -1;
}
p_queue->space[p_queue->tail] = data;
typedef struct ringq{
int head; /*头部,出队列方向*/
int tail; /*尾部,入队列方向*/
int size ; /*队列总尺寸*/
int space[RINGQ_MAX]; /*队列空间*/
}RINGQ;
/*
取消tag .限制读与写之间至少要留一个空间
队列空head == tail .
当head == tail时,tag = 0为空,等于= 1为满。
*/
extern int ringq_init(RINGQ *p_queue);
extern int ringq_free(RINGQ *p_queue);
/*加入数据到队列*/
extern int ringq_push(RINGQ *p_queue, int data);
PRINT_INT(data);
if(ringq_poll(p_queue, &data) >= 0)
PRINT_INT(data);
ringq_free(p_queue);
}
三.预留空间环境队列
-------------------------------------------------------------------
/*这个时候一定队列空了*/
if(p_queue->tail == p_queue->head)
{
p_queue->tag = 0;
}
return p_queue->tag ;
}
测试代码
/*测试第一种环形队列*/
void test5()
{
RINGQ rq, * p_queue;
int i, data;
队列为空:(q->head == q->tail) && (q->tag == 0)
队列为满: ((q->head == q->tail) && (q->tag == 1))
入队操作:如队列不满,则写入
q->tail = (q->tail + 1) % q->size ;
出队操作:如果队列不空,则从head处读出。
typedef struct ringq
{
int head; /*头部,出队列方向*/
int tail; /*尾部,入队列方向*/
int tag ;
int sizபைடு நூலகம் ; /*队列总尺寸*/
int space[RINGQ_MAX]; /*队列空间*/
}RINGQ;
初始化状态: q->head = q->tail = q->tag = 0;
环形队列实现原理/链式实现
环形队列是在实际编程极为有用的数据结构,它有如下特点。
它是一个首尾相连的FIFO的数据结构,采用数组的线性空间,数据组织简单。能很快知道队列是否满为空。能以很快速度的来存取数据。
因为有简单高效的原因,甚至在硬件都实现了环形队列.
环形队列广泛用于网络数据收发,和不同程序间数据交换(比如内核与应用程序大量交换数据,从硬件接收大量数据)均使用了环形队列.
PRINT_INT(data);
if(ringq_poll(p_queue, &data) >= 0)
PRINT_INT(data);
if(ringq_poll(p_queue, &data) >= 0)
PRINT_INT(data);
if(ringq_poll(p_queue, &data) >= 0)
#include "ringq.h"
int ringq_init(RINGQ *p_queue)
{
p_queue->size = QUEUE_MAX ;
p_queue->head = 0;
p_queue->tail = 0;
p_queue->tag = 0;
return 0;
}
int ringq_free(RINGQ *p_queue)
/*从队列取数据*/
extern int ringq_poll(RINGQ *p_queue, int *p_data);
#define ringq_is_empty(q) ( (q->head == q->tail) && (q->tag == 0))
#define ringq_is_full(q) ( (q->head == q->tail) && (q->tag == 1))
队列满是(tail+1)%MAX == head
初始化是head = tail = 0;
*/
extern int ringq_init(RINGQ * p_ringq);
extern int ringq_free(RINGQ * p_ringq);
extern int ringq_push(RINGQ * p_ringq,int data);
为了方便读写,还要用数组下标来指明队列的读写位置。head/tail.其中head指向可以读的位置,tail指向可以写的位置。
环形队列的关键是判断队列为空,还是为满。当tail追上head时,队列为满时,当head追上tail时,队列为空。但如何知道谁追上谁。还需要一些辅助的手段来判断.
如何判断环形队列为空,为满有两种判断方法。
1.是附加一个标志位tag
当head赶上tail,队列空,则令tag=0,
当tail赶上head,队列满,则令tag=1,
2.限制tail赶上head,即队尾结点与队首结点之间至少留有一个元素的空间。
队列空:head==tail
队列满:(tail+1)% MAXN ==head
二.附加标志实现算法