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

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

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


目录
相关文章
数据结构——二叉树的链式结构
数据结构——二叉树的链式结构
33 0
|
3月前
|
存储 索引
数据结构(顺序结构、链式结构、索引结构、散列结构)
数据结构(顺序结构、链式结构、索引结构、散列结构)
【初阶数据结构】二叉树链式结构的实现和遍历
在学习二叉树的基本操作前,需先要创建一棵二叉树,然后才能学习其相关的基本操作。由于现在大家对二叉树结构掌握还不够深入,为了降低大家学习成本,此处手动快速创建一棵简单的二叉树,快速进入二叉树操作学习,等二叉树结构了解的差不多时,我们反过头再来研究二叉树真正的创建方式。
|
5月前
|
存储
初阶数据结构(六)队列的介绍与实现
初阶数据结构(六)队列的介绍与实现
31 0
|
5月前
|
存储 编译器
初阶数据结构(五) 栈的介绍与实现
初阶数据结构(五) 栈的介绍与实现
43 0
|
19天前
|
存储 C语言
【数据结构】线性表的链式存储结构
【数据结构】线性表的链式存储结构
16 0
|
存储 算法
【链式二叉树】数据结构链式二叉树的(万字详解)
【链式二叉树】数据结构链式二叉树的(万字详解)
|
5月前
|
存储
初阶数据结构(四)带头双向链表
初阶数据结构(四)带头双向链表
27 0
|
2月前
|
C语言
C语言数据结构(队列、循环队列)
C语言数据结构(队列、循环队列)
12 0
|
3月前
|
算法
速学数据结构 | 循环队列怎么写才最高效?只需要掌握这些技巧
速学数据结构 | 循环队列怎么写才最高效?只需要掌握这些技巧
39 0
速学数据结构 | 循环队列怎么写才最高效?只需要掌握这些技巧

热门文章

最新文章