数据结构——循环队列的设计

目录

 提前说明

一、循环队列的定义

 循环队列设计的解释:

 二、循环队列的接口功能

 三、循环队列的实现

1.循环队列的定义

2.初始化数据 

3.入队列

4.出队列

5.查看队首

6.查看队尾

7.验空

 8.判满

9.销毁

四、完整代码


 提前说明

文章基于LeetCode的题目,并不是完整的循环列表,只涉及其中部分功能,循环队列的完整代码请移步其他文章,本文只实现部分功能。

一、循环队列的定义

定义:循环队列属于队列的一种,具有队列的功能,可以在头尾进行插入和删除,因为可以改变头尾指针的位置,所以具有在任意节点操作的功能。

特点:

1.循环队列允许元素在队尾插入,在队头删除,同时遵循先进先出的原则。

2.笔者推荐使用数组实现循环队列,数组相比链表节约了找尾这一步骤,更加方便的快速访问,同时循环队列用数组实现可以不用移动数组内的元素。

3.在大量添加和删除元素时,循环队列相比链表更有效率,因为它不需要频繁移动指针寻找元素。

4.缺陷:不支持随机访问,不能像数组一样直接访问特定位置的元素。比如不能实现二分查找。

 一般情况循环队列错误示范

 下面是正确的满循环队列

 

 循环队列设计的解释:

循环队列为空时,rear==front,在同一位置;循环队列为满时,按一般情况走下去rear==front。

队列满和空的条件居然一样!这就会出现问题,队列是满是空程序无法判断。

为了针对这样的情况,需要设计出一个空位置,不放任何元素,类比做哨兵卫,通过取%的方式判断队列排满。

 二、循环队列的接口功能

1.初始化:创造一个空的队列,底层是数组,头和尾指针指向同一节点,队列设置为空。

2.入队列:向循环队列插入一个元素。如果成功插入则返回真。

3.出队列:从循环队列中删除一个元素。如果成功删除则返回真。

4.查看队首:从队首获取元素。如果队列为空,返回 -1。

5.查看队尾:获取队尾元素。如果队列为空,返回 -1 。

6.验空:检查循环队列是否为空。

7.判满:检查循环队列是否已满。

8. 销毁:销毁开辟的数组。

 三、循环队列的实现

1.循环队列的定义


typedef struct {
    int* _a;//数组指针
    int _front;
    int _rear;
    int _k;//记录数组长度
} MyCircularQueue;

​

2.初始化数据 

MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue* p=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    p->_a=(int*)malloc(sizeof(int)*(k+1));
    p->_front=0;
    p->_rear=0;
    p->_k=k;
    return p;
}

3.入队列

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
     if(myCircularQueueIsFull(obj))//检验队列是否为满
     {
        return false;
     }

        obj->_a[obj->_rear]=value;
        obj->_rear++;
        obj->_rear %= (obj->_k+1);
        return true;  
}

 解释obj->_rear %= (obj->_k+1):_rear遇到以下情况时需要取%

 当队列满时直接返回错误;队列不满,头指针在原地,rear取%不影响,头指针不在原地,rear取%返回头。

4.出队列

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

解释:_front向后移动直接舍弃要删除的元素,与rear取%原理相同,同样都是返回原地

5.查看队首

int myCircularQueueFront(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
    {
        return -1;
    }

    return obj->_a[obj->_front];
}

6.查看队尾

int myCircularQueueRear(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
    else
    {
        int tail=obj->_rear-1;
        if(tail==-1)
        {
          tail=obj->_k;
        }
         return obj->_a[tail];
    }
}

 解释:tail为_数组下标,当rear有如下情况时

 

tail的值会变为-1,因此需要将k重新赋值给tail,以免发生越组访问。

7.验空

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    return obj->_front==obj->_rear;
}

 8.判满

bool myCircularQueueIsFull(MyCircularQueue* obj) {
    return (obj->_rear+1)%(obj->_k+1)==obj->_front;
}

9.销毁

void myCircularQueueFree(MyCircularQueue* obj) {
    free(obj->_a);
    free(obj);
}

四、完整代码

typedef struct {
    int* _a;//数组指针
    int _front;
    int _rear;
    int _k;//记录数组长度
} MyCircularQueue;

//初始化数据
MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue* p=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    p->_a=(int*)malloc(sizeof(int)*(k+1));
    p->_front=0;
    p->_rear=0;
    p->_k=k;
    return p;
}
//声明
bool myCircularQueueIsFull(MyCircularQueue* obj);
bool myCircularQueueIsEmpty(MyCircularQueue* obj);
//向循环队列插入一个元素。如果成功插入则返回真
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
     if(myCircularQueueIsFull(obj))
     {
        return false;
     }

        obj->_a[obj->_rear]=value;
        obj->_rear++;
        obj->_rear %= (obj->_k+1);
        return true;  
}
//从循环队列中删除一个元素。如果成功删除则返回真
bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
    {
        return false;
    }
    
    obj->_front++;
    obj->_front %=(obj->_k+1);
    return true;
}
//从队首获取元素。如果队列为空,返回 -1 
int myCircularQueueFront(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
    {
        return -1;
    }

    return obj->_a[obj->_front];
}
//获取队尾元素。如果队列为空,返回 -1 
int myCircularQueueRear(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
    else
    {
        int tail=obj->_rear-1;
        if(tail==-1)
        {
          tail=obj->_k;
        }
         return obj->_a[tail];
    }
}
//检查循环队列是否为空
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    return obj->_front==obj->_rear;
}
//检查循环队列是否已满
bool myCircularQueueIsFull(MyCircularQueue* obj) {
    return (obj->_rear+1)%(obj->_k+1)==obj->_front;
}

void myCircularQueueFree(MyCircularQueue* obj) {
    free(obj->_a);
    free(obj);
}

/**
 * Your MyCircularQueue struct will be instantiated and called as such:
 * MyCircularQueue* obj = myCircularQueueCreate(k);
 * bool param_1 = myCircularQueueEnQueue(obj, value);
 
 * bool param_2 = myCircularQueueDeQueue(obj);
 
 * int param_3 = myCircularQueueFront(obj);
 
 * int param_4 = myCircularQueueRear(obj);
 
 * bool param_5 = myCircularQueueIsEmpty(obj);
 
 * bool param_6 = myCircularQueueIsFull(obj);
 
 * myCircularQueueFree(obj);
*/

  • 19
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值