队列---面试知识点整理
数据结构包括逻辑结构和存储结构。
逻辑结构包括集合、线性结构、树形结构、图形结构。
存储结构包括顺序存储结构、链式存储结构、索引存储结构、哈希存储结构。
“线性表”中的“线性”是逻辑结构的概念,是指
(1)开始结点和终端结点都是唯一的;
(2)除了开始结点和终端结点,其余结点都有且仅有一个直接前驱,有且仅有一个直接后继。
“循环链表”中的“链表”是存储结构的概念,是指
不要求逻辑上相邻的结点在物理上也相邻,结点间的逻辑关系是由附加的指针字段表示的。
综上 ,循环链表也是链表的一种,链表满足线性表的条件,所以循环链表自然也属于线性表。
栈,它是一种运算受限的线性表。其限制是仅允许在表的一端进行插入和删除运算。这一端被称为栈顶,相对地,把另一端称为栈底。
队列,是一种特殊的 线性表 ,特殊之处在于它只允许在表的前端( front )进行删除操作,而在表的后端( rear )进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头
递归是栈实现的。栈是先进后出,也就是上次递归调用的时候,保存在栈顶, 在返回的时候出栈,所以是递归是依靠栈实现的.
PS: 非递归形式的深度优先搜索要用栈,而广度优先使用了队列。
某带链的队列初始状态为 front=rear=NULL 。经过一系列正常的入队与退队操作后, front=rear=10 。该队列中的元素个数为( )
往队列的队尾插入一个元素为入队,从队列的排头删除一个元素称为退队。初始时 front=rear=0 , front 总是指向队头元素的前一位置,入队一次 rear+1 ,退队一次 front+1 。队列队头队尾指针相同时队列为空。而带链的队列,由于每个元素都包含一个指针域指向下一个元素,当带链队列为空时 front=rear=Null ,插入第 1 个元素时, rear+1 指向该元素, front+1 也指向该元素,插入第 2 个元素时 rear+1 , front 不变,删除 1 个元素时 front+1 。即 front=rear 不为空时带链的队列中只有一个元素。
当队列中只有一个元素时,出队后需要清空对头和队尾指针。
线性结构与非线性结构,主要看元素之间的关系,如果是一对一的关系则是线性表,如果不是一对一的关系则是非线性表。
循环队列中,由于入队时尾指针向前追赶头指针;出队时头指针向前追赶尾指针,造成队空和队满时头尾指针均相等。因此,无法通过条件front==rear来判别队列是"空"还是"满"。
解决这个问题的方法至少有两种:
① 另设一布尔变量以区别队列的空和满;
②另一种方式就是数据结构常用的: 队满时:(rear+1)%n==front,n为队列长度(所用数组大小),由于rear,front均为所用空间的指针,循环只是逻辑上的循环,所以需要求余运算.
队列元素=(尾指针-头指针+队列容量)%队列容量。循环队列中的元素个数随队头指针与队尾指针的变化而动态变化
双端队列是一种同时具有队列和栈的性质的一种数据结构,在队列的两头都可以进行插入和删除的操作;输入受限的双端队列是指只能从队列一端输入,可以从两端输出的双端队列;同理,输出受限的双端队列是指只能从队列一端输出,可以从两端输入的双端队列;如果双端队列允许从一端输入,从一端输出,则是普通的队列,如果双端队列只允许从一端输入和输出则是栈。因此说双端队列同时具有队列和栈两种数据结构的性质。
Redis和kafka都是常见的开源队列。
队列是一种操作受限 的结构,即只能在队首删除和队尾插入
栈是解决封闭对应问题的有效方法。
比如在解析XML中,遇到一个<demo>标签(左标签)就入栈,遇到其子标签的左标签(如<subdemo>)同样入栈。遇到右标签(如</subdemo>或</demo>)就校验栈顶标签是否与该右标签对应,能对应就出栈,不能对应则说明标签不对称,是无效的XML文件
存储结构是数据的逻辑结构用计算机语言的实现,常见的存储结构有: 顺序存储 , 链式存储 , 索引存储 ,以及 散列存储 。其中散列所形成的存储结构叫 散列表(又叫哈希表) ,因此哈希表也是一种存储结构。栈只是一种抽象数据类型,是一种逻辑结构,栈逻辑结构对应的顺序存储结构为顺序栈,对应的链式存储结构为链栈,循环队列是顺序存储结构,链表是线性表的链式存储结构
用循环链表表示队列,必定有链表的头结点,题目中说链表设有尾指针。因此入队操作在链表尾插入,直接插入再尾指针指向的节点后面,时间复杂度是常数级的;出队操作在链表表头进行,也就是删除表头指向的节点,时间复杂度也是常数级的。
在栈中,栈底保持不变,有元素入栈,栈顶指针增加;有元素出栈,栈顶指针减小。在循环队列中,队头指针和队尾指针的动态变化决定队列的长度。在循环链表中,前一个结点指向后一个结点,而最后一个结点指向头结点,只有头结点是固定的。线性链表中,由于前一个结点包含下一个结点的指针,尾结点指针为空,要插入删除元素,只需要改变相应位置的结点指针即可,头指针和尾指针无法决定链表长度。
循环队列解决的是“假溢出”问题,但是仍然会出现真正的溢出问题。假溢出指的是下标溢出,真溢出指的是空间溢出。
DFS是深度优先搜索,是后进先出,所以需要借助于一个栈来实现。而BFS,也就是广度优先搜索才是借助一个队列来实现
循环队列,其队头指针为front,队尾指针为rear;循环队列长度为N。其队内有效长度为?(假设队头不存放数据) (rear - front + N) % N
下面数据结构能够支持随机的插入和删除操作、并具有较好的性能的是____。
1,数组是在定义的时候申请一块连续的内存空间,访问某个元素只需要通过下标就可以,但是随机插入和删除都要移动后面所有的元素,所以,数组肯定不行;
2,链表,是非连续的空间,通过指针访问,所以随机插入和删除通过指针之间的操作很方便,但是如果要查询一个数的时候还是得依次便利,但是题目问的是随机插入和删除,所以,链表可以;
3,栈,所有的操作都是在栈顶,如果要随机插入或者删除某个数也必须依次对其他数就行操作,所以,栈也排除;
4,队列,通过队头和队尾指针进行读入数据和删除数据,如果直接在队尾添加数据很方便,但是,题目中是随机,所以,队列排序;
5,哈希表通过键值对操作,只要知道相关的key很容易就行读取和删除,插入某个元素也通过key很方便,所以,哈希表肯定可以;
栈的常见应用:浏览器历史纪录,Android中的最近任务,Activity的启动模式,CPU中栈的实现,Word自动保存,解析计算式,解析xml/json
循环队列的相关条件和公式:
队尾指针是rear,队头是front,其中QueueSize为循环队列的最大长度
1.队空条件:rear==front
2.队满条件:(rear+1) %QueueSIze==front
3.计算队列长度:(rear-front+QueueSize)%QueueSize
4.入队:(rear+1)%QueueSize
5.出队:(front+1)%QueueSize