【数据结构初阶】顺序循环队列和链式循环队列

简介: 【数据结构初阶】顺序循环队列和链式循环队列

1.知识点

让我们先对比一下普通队列和循环队列

1b719e965e8a46b9a263875651ee1927.jpg

39cc38fc6fc341408645f7768870c472.png

cfff0c8ecda3460c99ec1b9d928920cf.png

第一个问题:顺序循环队列和链式循环队里怎么做到循环?


循环队列是定长的数组,循环数组在循环方面物理上肯定不能做到循环,所以我们采用逻辑上循环的方式,当tail或者front到了边界的时候,手动"拉到"合适的位置,逻辑上造成一种循环.


而循环链表在循环方面物理上是可以做到循环的(循环链表)

而逻辑上就更是自动->next就能回到合适的位置造成循环.


第二个问题:由于循环队列是定长的,定长的话和普通队列不一样,不定长的话,只用考虑为队列空的情况,定长的话,除了考虑为空的情况,还需要考虑队列为满的情况.


至于如何判断队列为空和队列满了?请往下看


回顾一下我们以前队列判空的逻辑:(指向同一个值为空的数组元素或者节点


顺序普通队列:a[front]==a[tail]


链式普通队列:front==tail


如果我们和之前一样的方式判断满的话,我们会发现


cb1f58b856c04870b9e1e832ce27f4d2.png


这判断队列满的方式怎么和判断队列空的方式一模一样,这可怎么整啊!倒时候没办法区分不是乱套了吗?!别急,有办法~~


d5b080ab5edf43f1ba6dce032db2a4f1.png


解决判断队列为空和队列满有两种解决方案:


方法一:

在MyCircularQueue结构体中设置一个size成员变量,用于记录实际的元素个数,而定长K是题目会给的,我们也相应的记录为capacity就行了,空就是size==0;满就是size==capacity;

方法二

多开一个空间,使得满的时候永远有一个位置不存数据,就好比这样就是满了

下面以方法2为例:


2bd934988d98487ea68dedd1f72db956.png


3e9d300362c14fc0868b8a7722702d61.png


特别注意:这里的方法二中的满的时候永远空出一个空间,不一定是最后一个空间!

当入队列时有元素出队列时此时就可以使得空出的那一个位置不是最后那个空间!例如上图链式循环队列.


2.顺序循环队列

49c7b561d7fb4d66b1d4dbb80e56ac83.png

typedef struct {
    int* a;
    int k;
    int front;
    int tail;
} MyCircularQueue;
MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue* obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    obj->a=(int*)malloc(sizeof(int)*(k+1));
    obj->k=k;
    obj->front=obj->tail=0;
    return obj;
}
bool myCircularQueueIsFull(MyCircularQueue* obj);
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    if(myCircularQueueIsFull(obj))
    {
        return false;
    }
    else 
    {
        obj->a[obj->tail]=value;
        //书写方式1:
        // obj->tail++;
        // if(obj->tail==obj->k+1)
        // {
        //     obj->tail=0;
        // }
        //书写方式2:
        obj->tail=(obj->tail+1)%(obj->k+1);
        return true;
    }
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj) ;
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
    {
        return false;
    }
    else 
    {
        //书写方式1:
        // obj->front++;
        // if(obj->front==obj->k+1)
        // {
        //     obj->front=0;
        // }
        //书写方式2:
        obj->front=(obj->front+1)%(obj->k+1);
        return true;
    }
}
int myCircularQueueFront(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
    else 
    {
        return obj->a[obj->front];
    }
}
int myCircularQueueRear(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
    else 
    {
        // int tailPrev=obj->tail-1;
        // if(tailPrev==-1)
        // {
        //     tailPrev=obj->k;
        // }
        // return obj->a[tailPrev];
        return obj->a[(obj->tail-1+obj->k+1)%(obj->k+1)];
    }
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    return obj->front==obj->tail;
}
bool myCircularQueueIsFull(MyCircularQueue* obj)
{
    // int tailNext=obj->tail+1;
    // if(tailNext==obj->k+1)
    // {
    //     tailNext=0;
    // }
    int tailNext=(obj->tail+1)%(obj->k+1);
    return obj->front==tailNext;
   // return obj->a[obj->tail+1];
}
void myCircularQueueFree(MyCircularQueue* obj) {
    free(obj->a);
    obj->tail=obj->front=0;
    obj->k=0;
    free(obj);
}

e7a5cd7989924db893378bdcc68b1a58.png

3.链式循环队列

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>;
#include<stdbool.h>
typedef struct ListNode
{
  int val;
  struct ListNode* next;
}ListNode;
typedef struct MyCirQue
{
  ListNode* front;
  ListNode* prev;
  ListNode* tail;
  int size;
}MyCirQue;
MyCirQue* MyCirQueInit(int k)
{
  MyCirQue* ps = (MyCirQue*)malloc(sizeof(MyCirQue));
  ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
  newnode->next = NULL;
  ps->prev = NULL;
  ps->front = ps->tail = newnode;
  ps->size = 0;
  while (--k)
  {
    ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
    newnode->next = NULL;
    ps->tail->next = newnode;
    ps->tail = ps->tail->next;
    ps->size++;
  }
  ps->tail->next = ps->front;
  ps->tail = ps->front;
}
bool MyCirQueIsEmpty(MyCirQue* ps)
{
  return ps->front == ps->tail;
}
bool MyCirQueIsFull(MyCirQue* ps)
{
  return ps->tail->next == ps->front;
}
bool MyCirQuePush(MyCirQue* ps, int x)
{
  if (MyCirQueIsFull(ps))
  {
    return false;
  }
  else
  {
    ps->tail->val = x;
    ps->prev = ps->tail;
    ps->tail = ps->tail->next;
    return true;
  }
}
bool MyCirQuePop(MyCirQue* ps)
{
  if (MyCirQueIsEmpty(ps))
  {
    return false;
  }
  else
  {
    ps->front = ps->front->next;
    return true;
  }
}
int MyCirQueFront(MyCirQue* ps)
{
  if (MyCirQueIsEmpty(ps))
  {
    return -100;
  }
  else
  {
    return ps->front->val;
  }
}
int MyCirQueTail(MyCirQue* ps)
{
  if (MyCirQueIsEmpty(ps))
  {
    return -100;
  }
  else
  {
    return ps->prev->val;
  }
}
void MyCirQuePrint(MyCirQue* ps)
{
  ListNode* cur = ps->front;
  while (cur != ps->tail)
  {
    printf("%d->", cur->val);
    cur = cur->next;
  }
  printf("NULL\n");
}
void SListDestory(MyCirQue* ps)
{
  ListNode* cur = ps->front;
  while (ps->size--)
  {
    ListNode* next = cur->next;
    free(cur);
    cur = next;
  }
}
void MyCirQueDestory(MyCirQue* ps)
{
  SListDestory(ps);
  free(ps);
}
int main()
{
  MyCirQue* ps = MyCirQueInit(5);
  MyCirQuePush(ps, 1);
  MyCirQuePush(ps, 2);
  MyCirQuePush(ps, 3);
  MyCirQuePush(ps, 4);
  MyCirQuePop(ps);
  MyCirQuePrint(ps);
  MyCirQueDestory(ps);
  return 0;
}

148caef79fce4facb83cb7054a24e4cb.png

4.一道妙的选择题

题目:

现有一顺序循环队列,其队头为front,队尾为rear,循环队列长度为N,最多存储N-1个数据。其队内有效长度为( B)

内容:

A.(rear - front + N) % N + 1


B.(rear - front + N) % N


C.(rear - front) % (N + 1)


D.(rear - front + N) % (N - 1)


答案:B

d05c8a19f4d14d3eaf1b0983d7fe852e.png


目录
相关文章
|
5月前
|
存储 算法
【数据结构和算法】--- 二叉树(4)--二叉树链式结构的实现(2)
【数据结构和算法】--- 二叉树(4)--二叉树链式结构的实现(2)
38 0
|
5月前
|
存储 算法
【数据结构和算法】--队列的特殊结构-循环队列
【数据结构和算法】--队列的特殊结构-循环队列
33 0
|
1月前
|
存储
【初阶数据结构】深入解析循环队列:探索底层逻辑
【初阶数据结构】深入解析循环队列:探索底层逻辑
|
4月前
|
存储 索引
【数据结构OJ题】设计循环队列
力扣题目——设计循环队列
35 1
【数据结构OJ题】设计循环队列
|
3月前
|
算法
【数据结构与算法】循环队列
【数据结构与算法】循环队列
24 0
|
5月前
【数据结构】链式二叉树的层序遍历
【数据结构】链式二叉树的层序遍历
37 5
|
5月前
|
存储 测试技术
【数据结构】手把手分析:链式二叉树的实现
【数据结构】手把手分析:链式二叉树的实现
37 5
|
5月前
|
存储 测试技术
【数据结构】最最基础的链式结构——单链表,还不会你就吃大亏了!
【数据结构】最最基础的链式结构——单链表,还不会你就吃大亏了!
52 5
|
5月前
|
存储 算法 调度
【数据结构与算法】详解循环队列:基于数组实现高效存储与访问
【数据结构与算法】详解循环队列:基于数组实现高效存储与访问
|
5月前
|
存储
数据结构初阶 堆(一)
数据结构初阶 堆(一)
31 1

热门文章

最新文章

下一篇
无影云桌面