队列练习之Example003-如果允许在循环队列的两端都可以进行插入和删除操作,分别写出从队尾删除和从队头插入的算法
Posted 二木成林
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了队列练习之Example003-如果允许在循环队列的两端都可以进行插入和删除操作,分别写出从队尾删除和从队头插入的算法相关的知识,希望对你有一定的参考价值。
Example003
题目
如果允许在循环队列的两端都可以进行插入和删除操作,要求:
- 写出循环队列的类型定义。
- 分别写出从队尾删除和从队头插入的算法。
分析
本题实际考查的是双端队列的代码实现。具体可参考:双端队列。
注意:
- 约定队头指针指向队头元素;队尾指针指向队尾元素的下一位置。
- 有些书中给出的代码实现,是约定的队头指针指向队头元素的前一位置,队尾指针指向队尾元素,具体根据实际情况来即可。
图解
略。
C实现
核心代码:
/**
* 双端队列结构体定义,跟循环队列的一样,只是 rear 在双端队列中名为 back
*/
typedef struct
/**
* 数据域,存储循环队列中的数据
*/
int data[MAXSIZE];
/**
* 指针域,存储循环队列中队头元素的位置
*/
int front;
/**
* 指针域,存储循环队列中队尾元素的位置
*/
int back;
DoubleEndedQueue;
/**
* 从队头将元素入队
* @param queue 双端队列
* @param ele 待入队的元素
* @return 如果队列已满则不能入队返回 0 表示入队失败;否则返回 1 表示入队成功
*/
int pushFront(DoubleEndedQueue *deque, int ele)
// 0.参数校验,如果队满则不能入队
if (isFull(*deque))
return 0;
// 1.将元素插入到队列的头部
// 1.1 由于队头指针指向队列的队头元素,所以先修改队头指针。新元素应该插入到原队头元素的前面,所以要队头指针减一,因为是循环队列,所以要对 MAXSIZE 取余
deque->front = (deque->front - 1 + MAXSIZE) % MAXSIZE;
// 1.2 再对队头指针所指向的位置进行赋值
deque->data[deque->front] = ele;
// 1.3 返回 1 表示入队成功
return 1;
/**
* 从队尾将元素出队
* @param deque 双端队列
* @param ele 用来保存出队元素
* @return 如果队空则返回 0 表示出队失败,否则返回 1 表示出队成功
*/
int popBack(DoubleEndedQueue *deque, int *ele)
// 0.参数校验,如果队空则不能出队
if (isEmpty(*deque))
return 0;
// 1.从队尾将元素出队
// 1.1 由于队尾指针指向队尾元素的下一个位置,所以先修改队尾指针,将其减一,但由于是循环队列,所以要对 MAXSIZE 取余
deque->back = (deque->back - 1 + MAXSIZE) % MAXSIZE;
// 1.2 然后取出当前队尾指针所指向的元素,就是待出队的元素
*ele = deque->data[deque->back];
// 1.3 返回 1 表示出队成功
return 1;
完整代码请参考:DoubleEndedQueue.c。
Java实现
核心代码:
public class DoubleEndedQueue
/**
* 声明一个双端队列(顺序存储的双端队列)
*/
private Queue deque;
/**
* 从队头将元素入队
*
* @param ele 待入队的元素
*
* @throws Exception 如果队列已满则抛出此异常
*/
public void pushFront(int ele) throws Exception
// 0.参数校验,如果队满则不能入队
if (isFull())
throw new Exception("队满则不能入队!");
// 1.将元素插入到队列的头部
// 1.1 由于队头指针指向队列的队头元素,所以先修改队头指针。新元素应该插入到原队头元素的前面,所以要队头指针减一,因为是循环队列,所以要对 MAXSIZE 取余
deque.front = (deque.front - 1 + MAXSIZE) % MAXSIZE;
// 1.2 再对队头指针所指向的位置进行赋值
deque.data[deque.front] = ele;
/**
* 从队尾将元素出队
*
* @return 出队元素
*
* @throws Exception 如果队空则抛出此异常
*/
public int popBack() throws Exception
// 0.参数校验,如果队空则不能出队
if (isEmpty())
throw new Exception("队空则不能出队!");
// 1.从队尾将元素出队
// 1.1 由于队尾指针指向队尾元素的下一个位置,所以先修改队尾指针,将其减一,但由于是循环队列,所以要对 MAXSIZE 取余
deque.back = (deque.back - 1 + MAXSIZE) % MAXSIZE;
// 1.2 然后取出当前队尾指针所指向的元素,就是待出队的元素
return deque.data[deque.back];
/**
* 双端队列定义,跟循环队列的一样,只是 rear 在双端队列中名为 back
*/
class Queue
/**
* 数据域,存储循环队列中的数据
*/
int[] data;
/**
* 指针域,存储循环队列中队头元素的位置
*/
int front;
/**
* 指针域,存储循环队列中队尾元素的位置
*/
int back;
完整代码请参考:DoubleEndedQueue.java。
测试代码请参考:DoubleEndedQueueTest.java。
以上是关于队列练习之Example003-如果允许在循环队列的两端都可以进行插入和删除操作,分别写出从队尾删除和从队头插入的算法的主要内容,如果未能解决你的问题,请参考以下文章
队列练习之Example001-用两个栈 s1 和 s2 来模拟一个队列,实现队列的出队入队队是否为空的运算
队列练习之Example006-设计队列要求入队时增加队列空间,出队后出队元素所占用空间可重复使用,以保持队列空间只增不减,并且要求入队操作和出队操作的时间复杂度都为O
队列练习之Example005-Q 是一个队列,S 是一个空栈,实现将队列中的元素逆置的算法
队列练习之Example002-用带头结点的循环链表表示队列,并且只设一个指针指向队尾结点,实现对应的入队列和出队列的算法