首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

【数据结构】详谈队列顺序存储及C语言实现

在栈中,我们将指向栈顶标志称为栈顶指针,在队列中同理: 指向标志称为尾指针(rear); 指向标志称为头指针(front); 这两个指针主要做用就是告诉我们元素哪里入队哪里...,我们可以通过静态数组来实现一块连续存储空间; 既然是静态数组,那么我们要想找到数组中不同位置元素那就需要数组下标,因此头指针与尾指针就需要是两个存放数组下标的整型变量,因此我们可以将其用C语言表述为...这里我们先放一放,后面再来讨论; 在定义好数据类型后,我们只需要通过类型来定义一个变量并即将该变量进行初始化,即可完成队列创建。定义变量都很简单,关键是这个初识我们应该如何表示?...我们来看一下下面的图片: 从上图中我们可以看到按照前面的分析,在创建数据类型时只定义静态数组与两个指针并将指针初始化为0情况下,我们要实现一个队列,那我们入队操作与操作都应该选择先执行入队或者...也就是说我们前面的分析只适合与创建好队列后初始化开始到销毁结束,中间流程都不能发生任何变化,即入队就要全部元素入满,就要直接到销毁。

42710

Java中栈和队列

遇到开括号时将其推入栈中,遇到闭括号时尝试栈中弹出一个开括号并检查是否匹配。 页面访问:在Web浏览器中,栈常用来实现前进和后退功能。当用户访问新页面时,前一个页面会被推入栈中。...递归过程每一步都在栈上有自己存储空间,直到达到基本情况。 数制转换:在进行数制转换时,如十进制转八进制或其他进制,可以利用栈来临时存储转换过程中产生余数,最后栈顶开始依次输出即得到转换结果。...常见方法及功能: 方法 功能 boolean offer(E e) 入队列 E poll() 队列 peek() 获取头元素 int size() 获取队列中有效元素个数 boolean isEmpty...):index=(index+array.length-offset)%array.length 如何区分空与满 通过添加size属性记录 保留一个位置 使用标记 3.4双端队列 双端队列是指允许两端都可以进行入队操作队列...,那就说明元素可以入队,也可以入队

15910
您找到你想要的搜索结果了吗?
是的
没有找到

数据结构和算法 Data Structure and Algorithm

但是对于链表就不是了,链表也没有下标的概念,只能通过头节点指针,每一个节点,依次往下找,因为下个节点位置信息只能通过上个节点知晓(这里只考虑单向链表),所以访链表中List(3)与List(10000...–静态链表– 使用静态链表存储数据,需要预先申请足够大一整块内存空间,也就是说,静态链表存储数据元素个数其创建那一刻就已经确定,后期无法更改。 ...报数而不被杀的人:相当于再从入队;     被杀的人:只;     留到最后的人:当队列长度为1时,再出一次,返回。...当数据项加入队列,首先出现在尾,随着首数据项移除,它逐渐接近首。 队列特征   (1)先进先出或先到先服务;   (2)队列只有一个入口和一个出口。   ...图中每个顶点,都是字典中键,该键对应值为“该顶点所指向图中其他顶点”。

67700

如何自己实现一个队列

本文介绍队列基本概念和实现。 队列常见操作 队列最常见操作是入队,拿排队买东西来说,入队就是新来一个人排在队伍后面,而出就是一个人已经结账离开。...队列基本实现考虑 与实现栈不同,它需要两个指针,一个指向头(front),一个指向尾(rear),这样才能方便地进行入队操作,因此队列实现要比栈难一些。...并且队列中数据如下: 0 1 2 3 4 10 11 12 13 14 front rear 这个时候头front处删除一个数据,是很容易。...这里就说明了队列实现需要考虑两个问题: 如何高效地将元素入队 如何判断队列为空或队列为满 当然了,如果你使用链表实现队列,那么入队也完全不需要搬移数据。...2时,表明队列满 入队入队前检查队列是否已满,如未满,尾加1取模,并赋值 前检查队列是否为空,如不空,则取值,并加1取模 代码 完整可运行代码实现如下: //arrayQueue.c #include

71210

死磕 java集合之PriorityBlockingQueue源码分析

点击链接直达【拜托,面试别再问我堆(排序)了!】...为0,相当于解锁; (6)其它线程在扩容过程中要让出CPU; (7)再次加锁; (8)新数组创建成功,把旧数组元素拷贝过来,并返回到offer()方法中继续添加元素操作; 阻塞队列方法也有四个...; }} 过程与PriorityQueue基本类似: (1)加锁; (2)判断是否成功,未成功就阻塞在notEmpty条件上; (3)时弹出堆顶元素,并把堆尾元素拿到堆顶; (4)再做自上而下堆化...; (5)解锁; 总结 (1)PriorityBlockingQueue整个入队过程与PriorityQueue基本是保持一致; (2)PriorityBlockingQueue使用一个锁+一个...notEmpty条件控制并发安全; (3)PriorityBlockingQueue扩容时使用一个单独变量CAS操作来控制只有一个线程进行扩容; (4)入队使用自下而上堆化; (5)使用自上而下堆化

30810

Java并发编程--BlockingQueue

1 18 --count; 19 notFull.signal(); //唤醒入队条件等待队列中线程 20 return x; 21 }       源码可以看出,大致步骤如下...4)完成后,释放锁,唤醒同步队列后继节点,     offer(e)&poll() 返回特殊值       当不能满足入队条件时,返回特殊值。...为了提高并发度和吞吐量,使用两把锁,takeLock只负责,putLock只负责入队入队可以同时进行,提高入队操作效率,增大队列吞吐量。...而LinkedBlockingQueue入队操作使用是不同锁,会有对count变量并发修改情况,所以使用原子变量保证线程安全。...例如:入队线程使用put方法在队列尾部插入一个元素,怎么保证出线程能看到这个元素?ArrayBlockingQueue入队使用同一个锁,所以没有可见性问题。

52030

几幅图,干趴队列

对于队列这样一个数据结构来说,它有两个常见动作: enqueue,我个人喜欢把它译作入队,指的是把元素放入队列这个动作。 dequeue,,指的是把元素队列中移除这个动作。...明白了队列基本操作后,我们来深入地思考一下,队列是如何工作。 1) 建立顺序队列结构需要为其静态分配或者动态申请一串连续存储空间。...4)时 检查队列是否为空,需要一个 isEmpty() 方法来判断; 用一个临时变量来保存元素,以便后返回; 每次在首删除一个元素时,FRONT 加 1; 如果是最后一个元素,重置 FRONT...可以把问题归咎于我们实现队列方式上,也可以浅显地认为基本类型队列存在有局限性。随着入队连续操作,队列中元素在不停地变化,队列所占存储空间也在分配连续空间中不停移动。...当队列第一次被填满了以后,了两个元素,此时下标为 0 和 1 两个位置空了出来,然后入队元素 6,意味着 6 变成了尾,也就是 REAR 等于 0 了;再入队元素 7,7 变成了尾,也就是 REAR

36620

数据结构【第六篇】队列 (queue) 实现与讲解

允许插入一段称作尾 (rear),允许删除一端称为头 (front) 队列数据元素又叫做队列元素,在队列中插入一个队列元素称为入队队列中删除一个队列元素称为 ,也正是因为队列只允许在一段插入...我们一步步分析一下: 我们先按照我们一般想法画出队列元素进出过程,例如队列元素 ?...这样设想,也就是根据我们前面食堂排队例子画出来,但是我们可以清晰看到,当a0后,a0后元素全部需要前移,将空位补上,但我们在计算机中讲究性能二字,如何可以提高出性能呢?...问题一 这个时候我们就需要考虑这样问题了: ① 如何为了解决只有一个元素时候,头和尾重合使得处理变得麻烦?...+ maxSize) % MaxSize 入队:rear = (rear + 1) % maxSize :front = (front + 1) % maxSize (一) 顺序队列类型定义

63770

循环队列出-数组循环队列

head永远指向该队列头元素,tail则指向该队列最后一个元素下一位置,当有入队操作时:   当有操作时:   当遇到操作时,head会移向下一元素位置。...当然,对于这种方式入队判断条件显然是head=tail,判断条件是tail=array.length(数组最后一个位置下一位置)。...但是如果你传入一个小于8参数,那么会默认使用我们上述介绍静态属性值作为长度。至于为什么这么做,因为这么做会大大提高我们在入队时候效率,我们等会儿会看到。   ...入队操作   由于实现了Deque,所以它是一个双向队列,支持从头部或者尾部添加节点,由于内部操作类似,我们只简单介绍尾部添加入队操作。...其实,虽然我们这个它实现了双端队列,并且我们本篇主要把他当做队列来研究,其实该类完全可以作为栈或者一些其他结构来使用,所以提供了一些其他方法循环队列出,但本质上还是某几个方法。

1.1K10

Java并发编程(七)ConcurrentLinkedQueue实现原理和源码分析

使用阻塞算法队列可以用一个锁(入队用同一把锁)或两个锁(入队用不同锁)等方式来实现,而非阻塞实现方式则可以使用循环CAS方式来实现,本节我们就来研究下ConcurrentLinkedQueue...这个特性把入队 / 时,原本需要一起原子化执行两个步骤分离开来,从而缩小了入队 / 时需要原子化更新值范围到唯一变量。这是非阻塞算法得以实现关键。...以批处理方式来更新head/tail,整体上减少入队 / 操作开销。 ?...上面的分析单线程入队角度来理解入队过程,但是多个线程同时进行入队情况就变得更加复杂,因为可能会出现其他线程插队情况。...3.队列 队列就是队列里返回一个节点元素,并清空该节点对元素引用。让我们通过每个节点出快照来观察下head节点变化。 ?

933100

Java并发容器--ConcurrentLinkedQueue

概述   ConcurrentLinkedQueue是一种基于链表实现无界非阻塞线程安全队列,遵循先入先出规则。   线程安全队列有两种实现方式:     阻塞方式:对入队操作加锁。...类图可以看出,ConcurrentLinkedQueue有head和tail两个volatile域,节点是用静态内部类Node表示,每个Node含有元素item和指向下一个节点指针next,都是volatile...其实它是一种低级别的优化手段,就是在不需要让共享变量修改立刻让其他线程可见时候,以设置普通变量方式来修改共享状态,可以减少不必要内存屏障,从而提高程序执行效率。     ...     和入队相似,时也不是每次都会更新head节点,当head节点item不为null时,直接弹出item;否则会更新head节点。...并且如果在遍历过程中,Queue有入队操作,会导致该方法统计结果不准确。所以size()方法不太有用。那如何判断Queue是否为空呢?

77430

并发编程常识

正如上图一样,我们使用管程把共享变量和对应入队enq和dep封装起来,线程A和线程B要进行队列操作就要使用管程提供enq和dep实现,enq和dep保持了互斥,同一时刻只有一个线程进入管程...., 而条件变量和条件变量等待队列就是实现同步,这里我要注意一个问题,就是用管程实现阻塞队列和管程内等待队列是不一样东西,我们举个例子,一个线程1对管程实现阻塞队列进行操作,前提条件就是阻塞队列不能为空...,而这个前提条件就是管程里面的条件变量,当阻塞队列出时候,发现阻塞队列为空,怎么办呢,此时就会进入等待,而这个等待就是管程里面的条件变量等待队列,然后又有一个线程2要对管程实现阻塞队列进行入队操作...,如果入队成功之后,此时阻塞队列不为空条件,对于线程1就已经满足了,线程2就会通知线程1,线程1就会条件变量等待队列出,但是并不会直接执行,而是进入管程入口等待队列, 使用管程写一个线程安全队列...对于阻塞队列出操作,如果阻塞队列为空,就需要等待阻塞对垒不为空,使用notEmpty.await 当入队成功,阻塞队列就不为空了,此时就要通知条件变量:notEmpry等待队列 当成功,阻塞队列不满

25410

深入理解循环队列----循环数组实现ArrayDeque

队列这种数据结构,无论你是用链表实现,还是用数组实现,它都是要有两个指针分别指向头和尾。在我们数组实现方式中,用两个int型变量用于记录头和索引。 ?...当遇到操作时,head会移向下一元素位置。当然,对于这种方式入队判断条件显然是head=tail,判断条件是tail=array.length(数组最后一个位置下一位置)。...但是如果你传入一个小于8参数,那么会默认使用我们上述介绍静态属性值作为elements长度。至于为什么这么做,因为这么做会大大提高我们在入队时候效率,我们等会儿会看到。...入队操作 由于ArrayDeque实现了Deque,所以它是一个双向队列,支持从头部或者尾部添加节点,由于内部操作类似,我们只简单介绍尾部添加入队操作。...操作 操作和入队一样,具有着多个不同方法,但是内部调用还是一个pollFirst方法,我们主要看下该方法具体实现即可: public E pollFirst() { int h

2.2K80

如何设计高并发接口?

ConcurrentLinkedQueue使用是CAS原语无锁队列实现,是一个异步队列,入队速度很快,进行了加锁,性能稍慢。...LinkedBlockingQueue也是阻塞队列,入队都用了加锁,当时候线程会暂时阻塞。...在请求预处理阶段,由于我们系统入队需求要远大于需求,一般不会出现情况,所以我们可以选择ConcurrentLinkedQueue来作为我们请求队列实现 请求接口合理设计 一个秒杀或者抢购页面...,通常分为2个部分,一个是静态HTML等内容,另一个就是参与秒杀Web后台请求接口。...当然,也有一些秒杀和抢购采用“滞后反馈”,就是说秒杀当下不知道结果,一段时间后才可以页面中看到用户是否秒杀成功。但是,这种属于“偷懒”行为,同时给用户体验也不好,容易被用户认为是“暗箱操作”。

1.3K30

高并发接口设计思路

ConcurrentLinkedQueue使用是CAS原语无锁队列实现,是一个异步队列,入队速度很快,进行了加锁,性能稍慢。...LinkedBlockingQueue也是阻塞队列,入队都用了加锁,当时候线程会暂时阻塞。...在请求预处理阶段,由于我们系统入队需求要远大于需求,一般不会出现情况,所以我们可以选择ConcurrentLinkedQueue来作为我们请求队列实现 1....请求接口合理设计 一个秒杀或者抢购页面,通常分为2个部分,一个是静态HTML等内容,另一个就是参与秒杀Web后台请求接口。...当然,也有一些秒杀和抢购采用“滞后反馈”,就是说秒杀当下不知道结果,一段时间后才可以页面中看到用户是否秒杀成功。但是,这种属于“偷懒”行为,同时给用户体验也不好,容易被用户认为是“暗箱操作”。

1.4K21

并发队列 – 有界阻塞队列 ArrayBlockingQueue 原理探究

如图ArrayBlockingQueue内部有个数组items用来存放队列元素,putindex下标标示入队元素下标,takeIndex是下标,count统计队列元素个数,定义可知道并没有使用volatile...另外有个独占锁lock用来对出入队操作加锁,这导致同时只有一个线程可以访问入队,另外notEmpty,notFull条件变量用来进行出入队同步。...0: i; } 这里由于在操作共享变量前加了锁,所以不存在内存不可见问题,加过锁后获取共享变量都是主内存获取,而不是在CPU缓存或者寄存器里面的值,释放锁后修改共享变量值会刷新会主内存中。...cast(items[i]); } 八、 size操作 获取队列元素个数,非常精确因为计算size时候加了独占锁,其他线程不能入队或者或者删除元素 publicintsize() {...其中offer,poll操作通过简单加锁进行入队操作,而put,take则使用了条件变量实现如果队列满则等待,如果队列空则等待,然后分别在出入队操作中发送信号激活等待线程实现同步。

56140

管程(Moniter): 并发编程基本心法

管程就是来解决这两个问题。 互斥:同一时刻只允许一个线程访问共享资源。 同步:线程之间如何通信、协作。 管程互斥与同步实现 它思路很简单,将共享变量以及对共享变量操作统一封装起来。...如下图所示,管程 A 将共享变量 data 和相关操作入队enq()、deq() 封装起来。线程 A 和线程 B想访问共享变量 data ,只能通过调用管程提供 enq() 和 deq() 。...我们通过一段代码说明,实现一个阻塞队列,队列分别有入队,都是要先获取互斥锁,就像管程中入口。...如果入队成功,那么队列就不空了,就需要通知条件变量:队列不空notEmpty对应等待队列。 如果成功,那就队列就不满了,就需要通知条件变量:队列不满notFull对应等待队列。...notEmpty.await(); } // 省略操作... // 后,通知可入队 notFull.signal(); }

90210

【地铁上面试题】--基础部分--数据结构与算法--栈和队列

新元素被添加到尾,而元素删除操作总是头进行。...使用两个指针,一个指向头,一个指向尾,来标记队列中元素位置。 入队操作时,将新元素添加到尾,同时更新尾指针。 操作时,头删除元素,同时更新头指针。...无论队列大小如何入队操作只涉及对尾指针更新以及对数组中指定位置赋值操作。因此,入队操作时间复杂度是常数级别的,与队列中元素数量无关。...4.2 操作 操作实现 操作用于队列中删除并返回头元素,以下是一个示例 C 语言代码实现: int dequeue(Queue* queue) { if (queue->front...无论队列中有多少个元素,操作所需额外空间都是固定。 4.3 队列其他操作 队列大小获取 要获取队列大小,可以定义一个函数来返回队列中元素数量。

36320

并发队列-有界阻塞队列ArrayBlockingQueue原理探究

image.png 如图ArrayBlockingQueue内部有个数组items用来存放队列元素,putindex下标标示入队元素下标,takeIndex是下标,count统计队列元素个数,定义可知道并没有使用...另外有个独占锁lock用来对出入队操作加锁,这导致同时只有一个线程可以访问入队,另外notEmpty,notFull条件变量用来进行出入队同步。...0 : i; } 这里由于在操作共享变量前加了锁,所以不存在内存不可见问题,加过锁后获取共享变量都是主内存获取,而不是在CPU缓存或者寄存器里面的值,释放锁后修改共享变量值会刷新会主内存中。...cast(items[i]); } 八、 size操作 获取队列元素个数,非常精确因为计算size时候加了独占锁,其他线程不能入队或者或者删除元素 public int size() {...其中offer,poll操作通过简单加锁进行入队操作,而put,take则使用了条件变量实现如果队列满则等待,如果队列空则等待,然后分别在出入队操作中发送信号激活等待线程实现同步。

40310

c语言面试知识点总结_c语言电话面试题

在函数体,一个被声明为静态变量在这一函数被调用过程中维持其值不变。 2). 一个被声明为静态变量可以被模块内所用函数访问,但不能被其他文件函数访问。它是一个本地全局变量。 3)....对于静态成员函数,只能访问静态成员函数和静态成员变量,不能访问非静态成员函数或者变量。...入队: 将新元素push入栈A; : (1)判断栈B是否为空; (2)如果不为空,则将栈A中所有元素依次pop并push到栈B; (3)将栈B栈顶元素pop; 这样实现队列入队平摊复杂度都还是...入队: 将新元素push入栈A; : (1)判断栈B是否为空; (2)如果不为空,则将栈A中所有元素依次pop并push到栈B; (3)将栈B栈顶元素pop; 36....='\0' ) { len++; } return len; }' ) { len++; } return len; } 这样实现队列入队平摊复杂度都还是O(1), 比上面的几种方法要好

81830
领券