《数据结构学习笔记---第九篇》---循环队列的实现

文章目录

1.循环队列的定义

2.循环队列的判空判满

3.创建队列并初始化

4.入队和出队

[5. 返回队尾队首元素](#5. 返回队尾队首元素)

6.释放循环队列


1.循环队列的定义

**定义:**存储队列元素的表从逻辑上被视为一个环。

我们此次实现的循环队列,采用顺序表

cpp 复制代码
typedef struct {
    int*a;
    int front;
    int rear;
    int k;
    
} MyCircularQueue;

本质上是一个出入受限的顺序表,那我们是怎么实现他的环状结构的呢?毕竟顺序表是一个线性的结构而不是环状的。

答 他用取模运算刚好在存储空间上变成了"环状"。

例如:我们要走一个环状顺序表

如果我们将rear=1;front=2在逻辑上我们可以正常移动,但其实我们物理存储上的指针已经溢出了,所以我们刚好可以取模来控制指针的移动。

如果我们尾指针前进一步就可以(Q.rear+1)% k,刚好可以到达front的位置。

2.循环队列的判空判满

如图我们可以看到,此时rear==front既可以是判空的条件,也可以是判满的条件,那我们应该怎么区分呢?有三种方法://这里的指针变量会和题目中的不太一样,但是判断逻辑相同

1.牺牲一个单元来进行区分

队满:(Q.rear+1)%MaxSize ==Q.front;

队空: Q.front==Q.rear

2.设置一个Size表示队列元素长度来判断。

**队满:**Size==MaxSize;

队空:Size==0

3.设置一个 tag标记

tag==0&& Q.front==Q.rear,队空;

tag==1&& Q.front==Q.rear,队满。

  • isEmpty(): 检查循环队列是否为空。
  • isFull(): 检查循环队列是否已满。
cpp 复制代码
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
      assert(obj);
    if(obj->rear==obj->front )
    {
        return  true;
    }
    return false ;
}



bool myCircularQueueIsFull(MyCircularQueue* obj) {
      assert(obj);
    if((obj->rear+1)%(obj->k+1)==obj->front )
    {
        return  true;
    }
    return false ;
}

3.创建队列并初始化

MyCircularQueue(k): 构造器,设置队列长度为 k

cpp 复制代码
MyCircularQueue* myCircularQueueCreate(int k)
{
   MyCircularQueue*obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));//创建一个循环的队列结构体指针节点
  obj->a=(int*)malloc(sizeof(int)*(k+1)) ;//队列长度为k,但是要多一个空间用来判断空还是满
  obj->front=obj->rear=0;
  obj->k=k;
  return obj;
}

队列长度为k,但是要多一个空间用来判断空还是满 ,所以我们用的是第一种判空判满策略,牺牲一个存储空间

4.入队和出队

入队操作: obj->a[obj->rear]=value;
obj->rear=(obj->rear+1)%(obj->k+1);// 先赋值再移动指针

出队操作obj->front=(obj->front+1)%(obj->k+1);// 直接移动指针

  • enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
  • deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
cpp 复制代码
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    assert(obj);
    if (myCircularQueueIsFull(obj))
    {
        return false;
    }
    obj->a[obj->rear]=value;
    obj->rear=(obj->rear+1)%(obj->k+1);
      return true;

}

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
     assert(obj);
    if (myCircularQueueIsEmpty(obj))
    {
        return false;
    }
     obj->front=(obj->front+1)%(obj->k+1);
     return true;
}

5. 返回队尾队首元素

  • Front: 从队首获取元素。如果队列为空,返回 -1 。
  • Rear: 获取队尾元素。如果队列为空,返回 -1 。
cpp 复制代码
int myCircularQueueFront(MyCircularQueue* obj) {
     assert(obj);
    if (myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
     return obj->a[obj->front];
    
}

int myCircularQueueRear(MyCircularQueue* obj) {
      assert(obj);
    if (myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
    else{
     int rear=obj->rear==0 ? obj->k : obj->rear-1;
    return obj->a[rear];  
    }
}

int rear=obj->rear==0 ? obj->k : obj->rear-1; 由于队尾后面还有一个用于判空判满的空间,如果rear刚好指向这片空间,他实际上是指向的真正的队尾下标为k;如果不为0说明他指向的空间为正常的前驱结点。

6.释放循环队列

**切记:**先释放结构体指针指向的创建的队列所在的空间,再去释放结构体指针的空间。

cpp 复制代码
void myCircularQueueFree(MyCircularQueue* obj) {
    free(obj->a);
    free(obj);
}
相关推荐
Yan.love6 分钟前
开发场景中Java 集合的最佳选择
java·数据结构·链表
stm 学习ing9 分钟前
HDLBits训练5
c语言·fpga开发·fpga·eda·hdlbits·pld·hdl语言
AC使者12 分钟前
#B1630. 数字走向4
算法
冠位观测者16 分钟前
【Leetcode 每日一题】2545. 根据第 K 场考试的分数排序
数据结构·算法·leetcode
古希腊掌管学习的神1 小时前
[搜广推]王树森推荐系统笔记——曝光过滤 & Bloom Filter
算法·推荐算法
qystca1 小时前
洛谷 P1706 全排列问题 C语言
算法
浊酒南街1 小时前
决策树(理论知识1)
算法·决策树·机器学习
就爱学编程1 小时前
重生之我在异世界学编程之C语言小项目:通讯录
c语言·开发语言·数据结构·算法
学术头条1 小时前
清华、智谱团队:探索 RLHF 的 scaling laws
人工智能·深度学习·算法·机器学习·语言模型·计算语言学
Schwertlilien2 小时前
图像处理-Ch4-频率域处理
算法