① 循环队列中入队与出队算法
如果循环队列每个元素有两个指针,一个指向其前面的元素pPre,一个指向后面的元素pNext,出对和入队就是修改一下指针啊。
比如指向要出队的元素的指针是 pDel,那么出队就应该是:
pDel->pPre->pNext = pDel->pNext;
pDel->pNext->pPre = pDel->pPre;
如果循环队列每个元素只有一个指向其后元素的指针pNext,那么需要遍历整个队列,找到要出队元素的前一个元素,然后就和上面的算法差不多了。
如果经常要进行出队操作,在设计数据结构的时候还是建议每个元素使用两个指针。
② 求循环队列的元素个数算法,已知front 和 rear,还有容量数,怎么求队列中的循环元素个数
如果是用数组实现的 用队尾减队头再模数组长度;如果是链表 就要有个计数变量了。
front为对头指针,rear为对尾指针,n为队列最大元素个数。队列元素个数=(rear-front+1+n)%n %是求余数。
循环队列的元素个数计算公式:
如果rear<front结果是rear-front+maxsize;
如果rear>front结果是rear-front;
为了用一个表达式同时表达两者,用(rear-front+maxsize)%maxsize;
假设maxsize=10;
rear=1 front=9,那么结果是2;
rear=9 front=1,那么结果是8。
(2)循环队列的算法描述扩展阅读
循环队列中,由于入队时尾指针向前追赶头指针;出队时头指针向前追赶尾指针,造成队空和队满时头尾指针均相等。因此,无法通过条件front==rear来判别队列是"空"还是"满"。
解决这个问题的方法至少有两种:
① 另设一布尔变量以区别队列的空和满;
②另一种方式就是数据结构常用的: 队满时:(rear+1)%n==front,n为队列长度(所用数组大小),由于rear,front均为所用空间的指针,循环只是逻辑上的循环,所以需要求余运算。
队已满,但是rear(5)+1=6!=front(0),对空间长度求余,作用就在此6%6=0=front(0)。
③ 对于循环队列,试写出求队列长度的算法.
include<iostream>
using namespace std;
#define MAX_QSIZE 5
typedef int ElemType;
typedef struct SqQueue //循环队列结构体定义
{
ElemType *base;
int front;
int rear;};
void InitQueue(SqQueue *&Q)
{
Q=(SqQueue *)malloc(MAX_QSIZE*sizeof(SqQueue));
Q->rear=Q->front;
}
int EmptyQueue(SqQueue *Q)
{
if(Q->rear==Q->front)
return 0;
else return 1;
}
void DestroyQueue(SqQueue *Q)
{
if(Q->base) free(Q->base);
Q->base=NULL;
Q->front=Q->rear;
}
void ClearQueue(SqQueue *Q)
{
Q->rear=Q->front;
}
int LenghtQueue(SqQueue *Q) //求队列长度函数
{
return (Q->front-Q->rear+MAX_QSIZE)%MAX_QSIZE;
}
int EnQueue(SqQueue *&Q,ElemType &e) //入队操作
{
if((Q->rear+1)%MAX_QSIZE==Q->front)
return 0;
else Q->base[Q->rear]=e;
Q->rear=(Q->rear+1)%MAX_QSIZE;
return 1;
}
int DeQueue(SqQueue *&Q,ElemType &e) //出队操作
{
if(Q->rear==Q->front)
return 0;
else e=Q->base[Q->front];
cout<<e<<endl;
Q->front=(Q->front+1)%MAX_QSIZE;
return 1;
}
int main()
{
SqQueue *Q; InitQueue(Q);
int a[9]={0,1,2,3,4,5,6,7,8};
for(int i=0;i<9;i++)
{
EnQueue(Q,a[i]);
}
cout<<LengthQueue(Q)<<endl; return 0;
for(i=0;i<9;i++)
{
DeQueue(Q,a[i]);
}
}
④ 循环队列FIFO原理及C实现
循环队列概念与基本原理
循环队列,本质上是对顺序队列进行尾部连通形成闭合环形逻辑链,以此提升空间利用效率。当头指针遇到尾指针时,循环继续从头部开始,如同链条一般环环相扣。
构建一个循环队列结构体包含三个核心组件:指针front指头元素索引、指针指向元素的结构体struct type *fifo以及尾元素索引tail。同时,设定队列容量capacity。
实例展示
初始化循环队列流程:分配连续内存存储元素。
循环队列销毁与空/满状态判定:队列空状态在初始化时front置-1;出队后,front自增,若front回到tail说明队空,重新设定front和tail皆为-1。若front到达尾或当front回到0且tail为capacity-1时,则队列为满。
循环队列操作流程
入队操作:尾元素索引后移,即自增tail值。队空时,首次元素入队,front、tail均指向首元素。其他情况入队时,仅需自增tail。
出队操作:移除头元素,即递增front值。front与tail相遇时,视为队空,需将front、tail重新置为-1。其他情况下,直接丢弃front元素,后移front。
总元素数量与有效元素计数
通过尾索引减去头索引可得出总元素数,考虑到循环特性,实际可能为tail与front之差模队列容量。有效元素数量即为上述差值。
循环队列遍历与获取元素
循环队列遍历需遵循环形结构,获取队尾元素和队首元素需分别处理,具体算法需根据队列实现进行调整。
实际应用与验证
设计一套简单测试流程,验证循环队列实现逻辑与性能。这包括循环队列初始化、数据插入、数据检索和清理等操作,以及通过比较预期结果和实际结果验证正确性。
⑤ 数据结构循环队列问题
网络版本是对的。你没理解“队列非空时front和rear分别指向队头元素和队尾元索”,根据这句话当队列只有一个元素时,front==rear;当队为空时,front==(rear+1)%n;进队的操作为:rear = (rear + 1) % n ;Queue[rear] = elem ;元素正好在下标为0的位置,此时front==rear==0。“队列非空时front和rear分别指向队头元素和队尾元索”意思就是front和rear都是“实指”,而你的理解中front是“虚指”,不同教材采用的方法不一样,一般题目中会说明
⑥ 数据结构—队列
队列 (queue)是一种先进先出的线性表。它只允许在表的一端进行插入,在另一端进行删除,这如同我们日常生活中的排列是一致的,最早入队的元素最早离开。
队尾 (rear)是队列中允许插入的一端, 队头 (front)是队列中允许删除的一端。
队列如同栈一样,也同样有两种存储表示,分别是顺序表示和链式表示。
和顺序栈类似,在队列的顺序存储结构中,除了用一组地址连续的存储单元依次存放从队列头到对列尾的元素之外,需要设置两个指针front和rear分别指示队列头元素和尾元素的位置。
队列的顺序存储结构表示如下:
为方便C语言描述起见,约定:初始化建空队列时,front=rear=0,每当插入新元素至队尾时,“尾指针增一”,每当删除头元素时,“头指针增一”。因此,在非空队列中,头指针始终指向队列头元素,而尾指针始终指向队尾元素的下一个位置。
循环对列 是将顺序队列变成一个环状的空间,用这种方法可以解决队列“假溢出”问题。
“假溢出” 是指队列实际可用空间没有占满,但是不能向队列中添加新的队尾元素,否则会出现溢出的现象的情况。
在循环队列中,头尾指针以及队列元素之间的关系不发生改变,只是在循环队列中头尾指针“依次循环增一”的操作可用模运算实现。通过取模,头指针和尾指针就可以在顺序表空间内以头尾衔接的方式“循环”移动。
循环队列的基本操作算法描述:
链队是指采用链式存储结构实现的队列。通常链队用单链表来表示,一个链队显然需要两个分别指示对头和队尾的指针(分别称为头指针和尾指针)才能唯一确定。为了操作方便,同线性表的单链表一样,为链队添加头结点,并规定头指针始终指向头结点。
链队列存储结构表示如下:
链队操作即为单链表插入和删除操作的特殊情况,只是需要进一步修改尾指针或头指针。
链队列的基本操作算法描述:
⑦ 关于循环队列的问题:
其实算法是这样的,都是队尾减去队头
比如第一题队尾减队头=10-45=-35,这样是负的,说明了队头跑到了队尾的后面去了,因为循环的关系这个是正常的,我们只要再加上容量就是答案了-35+50=15
第二题也一样队尾减队头=29+5这里队尾本来就在队头后面,所以不用加了,就是负的时候要加正的时候不用了,懂了吗?