700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 数据结构和算法学习记录——设计循环队列(数组实现循环队列)核心思路 题解过程 完

数据结构和算法学习记录——设计循环队列(数组实现循环队列)核心思路 题解过程 完

时间:2019-09-23 17:26:34

相关推荐

数据结构和算法学习记录——设计循环队列(数组实现循环队列)核心思路 题解过程 完

目录

题目描述

题目示例

核心思路

链表实现

数组实现

重点

题解过程

结构体类型定义

创建一个循环队列并初始化

判断循环队列为空或为满

入队列函数

出队列函数

取队头数据

取队尾数据

销毁循环队列

完整题解

题目来源:力扣

题目描述

设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。

循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。

你的实现应该支持如下操作:

MyCircularQueue(k): 构造器,设置队列长度为 k 。Front: 从队首获取元素。如果队列为空,返回 -1 。Rear: 获取队尾元素。如果队列为空,返回 -1 。enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。isEmpty(): 检查循环队列是否为空。isFull(): 检查循环队列是否已满。

题目示例

MyCircularQueue circularQueue = new MyCircularQueue(3); // 设置长度为 3circularQueue.enQueue(1); // 返回 truecircularQueue.enQueue(2); // 返回 truecircularQueue.enQueue(3); // 返回 truecircularQueue.enQueue(4); // 返回 false,队列已满circularQueue.Rear(); // 返回 3circularQueue.isFull(); // 返回 truecircularQueue.deQueue(); // 返回 truecircularQueue.enQueue(4); // 返回 truecircularQueue.Rear(); // 返回 4

核心思路

循环队列可以用链表实现,也可以用数组实现。

链表实现

数组实现

重点

无论使用数组实现还是链表实现,循环队列都是需要多开一个空间。也就是说,当我们需要存n个数据,那使用循环队列的话,就要开n+1个空间,否则无法判断队列为空以及队列为满。

head指向头,tail指向尾,n表示循环队列能存储多少个数据。

数组循环列队

判空条件:head == tail

判满条件:head == (tail+1) %(n+ 1)

(例如:一个循环队列能存储3个数据,那么它循环队列满的情况下,tail指向的位置就是第五个,下标为3; (3(tail) + 1) % (3(n) + 1)) = 0 == head)

链表循环队列

判空条件:head == tail

判满条件:head == tail-> next

题解过程

数组实现

结构体类型定义

因为循环队列的大小题目要求中是在创建队列函数中进行malloc的,所以我们设计结构体时,就创建指针变量,用于后面存储函数中malloc的地址;创建两个下标,分别指向头和尾;创建一个变量记录循环队列的存储容量。

typedef struct{int * a;int head;int tail;int k;} MyCircularQueue;

创建一个循环队列并初始化

先开辟一个循环队列结构体大小的空间,再开辟循环队列结构体内部数组大小的空间;并进行初始化。

MyCircularQueue* myCircularQueueCreate(int k){MyCircularQueue* cq = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));cq->a = (int*)malloc(sizeof(int) * (k + 1));cq->head = cq->tail = 0;cq->k = k;return cq;}

判断循环队列为空或为满

根据前面判空判满的条件直接写即可

bool myCircularQueueIsEmpty(MyCircularQueue* obj){return obj->head == obj->tail;}

bool myCircularQueueIsFull(MyCircularQueue* obj){return (obj->tail+1) % (obj->k+1) == obj->head;}

入队列函数

判断队列是否为满,为满的话直接返回false;不为满则插入数据后,++tail,同时++tail时会有两种情况:

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value){if(myCircularQueueIsFull(obj))return false;obj->a[obj->tail] = value;(obj->tail)++;obj->tail %= (obj->k+1);return true;}

出队列函数

思路与入队列是一致的,只不过移动的从tail变成head,换成用head来操作即可。

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

取队头数据

取队头很简单,head指向的就是队头的数据。注意题目要求:循环队列为空的话就返回-1。

int myCircularQueueFront(MyCircularQueue* obj){if(myCircularQueueIsEmpty(obj))return -1;elsereturn obj->a[obj->head];}

取队尾数据

取队尾会有两种情况:

情况二可以有两种解决方法:

判断 当tail == 0时,取数组下标为n的数据作统一计算处理,建立一个下标变量i,i = (tail + n)%(n+1)。取下标为i的数据即为队尾数据。 例:取情况一的队尾-> i = (3 + 3) % (3 + 1) = 2,下标为2的数据正是队尾数据[3]; 再取情况二的队尾-> i = (0 + 3) % (3 + 1) = 3,下标为3的数据正是队尾数据[4]。

//第一种// int myCircularQueueRear(MyCircularQueue* obj)// {//if(myCircularQueueIsEmpty(obj))// return -1;//if(obj->tail == 0)// return obj->a[obj->l];//else// return obj->a[obj->tail-1];// }//第二种int myCircularQueueRear(MyCircularQueue* obj){if(myCircularQueueIsEmpty(obj))return -1;else{int i = ((obj->tail)+(obj->k)) % ((obj->k)+1);return obj->a[i];}}

销毁循环队列

注意是有两层的空间需要free,由内到外free即可。

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

完整题解

typedef struct{int * a;int head;int tail;int k;} MyCircularQueue;MyCircularQueue* myCircularQueueCreate(int k){MyCircularQueue* cq = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));cq->a = (int*)malloc(sizeof(int) * (k + 1));cq->head = cq->tail = 0;cq->k = k;return cq;}bool myCircularQueueIsEmpty(MyCircularQueue* obj){return obj->head == obj->tail;}bool myCircularQueueIsFull(MyCircularQueue* obj){return (obj->tail+1) % (obj->k+1) == obj->head;}bool myCircularQueueEnQueue(MyCircularQueue* obj, int value){if(myCircularQueueIsFull(obj))return false;obj->a[obj->tail] = value;(obj->tail)++;obj->tail %= (obj->k+1);return true;}bool myCircularQueueDeQueue(MyCircularQueue* obj){if(myCircularQueueIsEmpty(obj))return false;(obj->head)++;obj->head %= (obj->k+1);return true;}int myCircularQueueFront(MyCircularQueue* obj){if(myCircularQueueIsEmpty(obj))return -1;elsereturn obj->a[obj->head];}//第一种// int myCircularQueueRear(MyCircularQueue* obj)// {//if(myCircularQueueIsEmpty(obj))// return -1;//if(obj->tail == 0)// return obj->a[obj->l];//else// return obj->a[obj->tail-1];// }//第二种int myCircularQueueRear(MyCircularQueue* obj){if(myCircularQueueIsEmpty(obj))return -1;else{int i = ((obj->tail)+(obj->k)) % ((obj->k)+1);return obj->a[i];}}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);*/

end

学习自:比特徐靖杭——数据结构与算法课程

数据结构和算法学习记录——设计循环队列(数组实现循环队列)核心思路 题解过程 完整题解

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。