队列

队列简称队, 也是一种操作受限的线性表, 只允许在表的一端进行插入, 而在表的另一端进行删除.其特点为”先进先出(FIFO)”,故又称为先进先出的线性表,简单队列如图所示:

循环队列

顺序队列有一个先天不足, 那就是空间利用率不高, 会产生”假溢出”现象,即:其实队列中还有空闲的空间以存储元素, 但我们在判断队列是否还有空间时, 队列告诉我们队列已经满了, 因此这种溢出并不是真正的溢出, 在data数组中依然存在可以放置元素的空位置, 所以说这是一种”假溢出”;

于是我们就引入了循环队列的概念, 将顺序队列臆造为一个环状的空间, 即把存储队列元素的表从逻辑上看成一个环, 称为循环队列,其示意图如下:

注意:如图中所示,我们的循环队列为了在实现上的便利, 会有一个位置的空闲, m_front(如图中的front)指针总会指向一个元素值为空的位置,因此(m_front+1)%capacity才真正的指向队首元素, 而m_rear(图中为rear)才指向一个真实存在的队尾元素;

//循环队列的实现与解析
template <typename Type>
class MyQueue
{template <typename T>friend ostream &operator<<(std::ostream &os, const MyQueue<T> &queue);
public:MyQueue(int queueSize = 64);~MyQueue();void push(const Type &item);void pop() throw (std::range_error);const Type &front() const throw (std::range_error);const Type &rear() const throw (std::range_error);bool isEmpty() const;private:Type *m_queue;int m_front;    //队首指针(其实(m_front+1)%capacity才真正的指向队首元素)int m_rear;     //队尾指针int capacity;   //队列的内存大小, 但实际可用的大小为capacity-1
};
template <typename Type>
MyQueue<Type>::MyQueue(int queueSize): capacity(queueSize)
{if (queueSize < 1)throw std::range_error("queueSize must >= 1");m_queue = new Type[capacity];if (m_queue == NULL)throw std::bad_alloc();m_front = m_rear = 0;
}
template <typename Type>
MyQueue<Type>::~MyQueue()
{delete []m_queue;m_queue = NULL;m_front = m_rear = 0;capacity = -1;
}
template <typename Type>
inline bool MyQueue<Type>::isEmpty() const
{return m_front == m_rear;
}
template <typename Type>
inline void MyQueue<Type>::push(const Type &item)
{if ((m_rear+1)%capacity == m_front) //队列已满{Type *newQueue = new Type[2 * capacity];    //新队列的长度为原队列的2倍if (newQueue == NULL)throw std::bad_alloc();int start = (m_front+1)%capacity;   //数据序列的起始地址if (start <= 1) //队列指针尚未回绕{//只需拷贝一次:从start所指向的元素直到m_rear所指向的元素//std::copy(m_queue+start, m_queue+start+capacity-1, newQueue);std::copy(m_queue+start, m_queue+m_rear+1, newQueue);}else{//需要拷贝两次//1:从start所指向的元素直到数组(不是队列)末尾std::copy(m_queue+start, m_queue+capacity, newQueue);//2:从数组(不是队列)起始直到队列末尾std::copy(m_queue, m_queue+m_rear+1, newQueue+capacity-start);}//重新设置指针位置:详细信息请看下面图解m_front = 2*capacity-1;m_rear = capacity-2;capacity *= 2;delete []m_queue;m_queue = newQueue;}//队尾指针后移//注意:此处m_front+1可能需要回绕m_rear = (m_rear+1)%capacity;m_queue[m_rear] = item;
}
template <typename Type>
inline const Type &MyQueue<Type>::front() const
throw (std::range_error)
{if (isEmpty())throw range_error("queue is empty");//注意:此处m_front+1可能需要回绕return m_queue[(m_front+1)%capacity];
}template <typename Type>
inline const Type &MyQueue<Type>::rear() const
throw (std::range_error)
{if (isEmpty())throw range_error("queue is empty");return m_queue[m_rear];
}
template <typename Type>
inline void MyQueue<Type>::pop()
throw (std::range_error)
{if (isEmpty())throw range_error("queue is empty");//注意:此处m_front+1可能需要回绕m_front = (m_front+1)%capacity;m_queue[m_front].~Type();   //显示调用析构函数以销毁(析构)对象
}
//输出队列所有内容以做测试
template <typename Type>
ostream &operator<<(ostream &os, const MyQueue<Type> &queue)
{for (int i = (queue.m_front+1)%(queue.capacity);i <= queue.m_rear; /**空**/ ){os << queue.m_queue[i] << ' ';if (i == queue.m_rear)break;elsei = (i+1)%(queue.capacity);}return os;
}

补充说明

当队列已满时的两类扩充操作:

扩充之后的内存布局:

附-测试代码:

int main()
{MyQueue<char> cQueue(3);cQueue.push('A');cQueue.push('B');//因为cQueue实际能够用的大小为2, 所以此处会对数组进行放大cQueue.push('C');cout << cQueue << endl;cout << "front = " << cQueue.front() << ", rear = "<< cQueue.rear() << endl;cQueue.pop();cQueue.pop();cQueue.push('D');cQueue.push('E');cQueue.push('F');//此时queue的m_rear会进行回绕cQueue.push('G');cQueue.pop();cQueue.push('H');//此时队列已满, 再添加元素则会进行对队列扩张//此时m_rear已经回绕, 则会触发两次拷贝操作cQueue.push('I');//验证是否能够正常工作cout << cQueue << endl;cout << "front = " << cQueue.front() << ", rear = "<< cQueue.rear() << endl;for (char ch = '1'; ch <= '9'; ++ch)cQueue.push(ch);for (int i = 0; i < 4; ++i)cQueue.pop();cout << cQueue << endl;cout << "front = " << cQueue.front() << ", rear = "<< cQueue.rear() << endl;return 0;
}

数据结构基础(7) --循环队列的设计与实现相关推荐

  1. 数据结构与算法 | 循环队列

    循环队列 实际中我们还会用到一种队列叫做循环队列,这种队列把存储空间前后连接起来,形成像环一样的结构,解决了内存空间浪费的问题 这里我们用顺序结构来实现,因为为了防止溢出的情况,这里我们需要多开一个数 ...

  2. 三星手机电池循环清零代码_数据结构(C语言)-循环队列基本操作

    队列是一种先进先出(first in first out,FIFO)的线性表,是一种常用的数据结构. 它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列 ...

  3. 数据结构(c/c++)—循环队列的判断空满方式

    文章目录 前言 队列的数据结构 初始化 一.舍弃空间 二.不舍弃空间 1.计数器 2.设置标志位 前言 我们这里一共三个方法,通过是否舍弃空间来实现队列空满的判断. 队列的数据结构 const int ...

  4. 【数据结构】顺序循环队列及其实现(C语言)

    给定一个大小为MAXSIZE的数组储存一个队列,经过若干次的插入和删除以后,当队尾指针 rear = MAXSIZE 时,呈现队列满的状态,而事实上数组的前部可能还有空闲的位置.为了有效地利用空间,引 ...

  5. 2021 - 9 下旬 数据结构-线性表-循环队列-java实现代码

    //循环队列,本质就是用动态数组实现的,且出队入队时间复杂度均O(1)的队列 //相比普通队列,增设一个front指针,代表队头,代表下一个出队的元素 //循环队列的重点在于队头队尾的元素的下标的计算 ...

  6. 数据结构之顺序循环队列

    顺序循环队列 思维导图: 队列的定义: 队列的特点 队列的基本操作: 顺序循环队列基本操作的实现: 情况一:rear和front指向同一位置时 队列定义: 队列初始化: 入队: 出队: 队列判空: 返 ...

  7. 数据结构初学之循环队列补充

    求循环队列的长度 分析: 1.当队尾指针rear指向的结点的位置下标大于队头指针front指向的结点的位置下标时(即队尾指针在队头指针的后面时), 队列的长度为len = rear - front; ...

  8. 数据结构c语言循环队列代码,数据结构C语言实现----循环队列

    代码如下: #include #include typedef char ElemType; #define MAXQUEUE 100 typedef struct { ElemType *base; ...

  9. 《数据结构》之循环队列及代码

    一.引入 队列的顺序实现指内存中分配一片连续的存储单元用来存放数据,再设两个指针:队头指针front指向队头元素,队尾指针rear指向队尾元素或者队尾元素的下一个位置此处采用指向队尾元素下一个位置为例 ...

最新文章

  1. mysql库可以无限创建吗_mysql 创建库
  2. sqlmap os shell解析
  3. Spring Cloud配置中心获取不到最新配置信息的问题
  4. php filter 文件包含,php://filter(文件包含漏洞利用)及php://input
  5. 【学习笔记】Django
  6. Ubuntu 16.04工具栏靠下设置
  7. 九度OJ 1437 To Fill or Not to Fill -- 贪心算法
  8. 控制台程序隐藏方法总结(四种)
  9. 云米冰箱能控制扫地机器人_既能解放劳动力又能提升家庭幸福指数的小家电,云米互联网扫地机Pro开箱!...
  10. c语言判断是否是回文字符串
  11. UIScrollView autolayout
  12. springsecurity 不允许session并行登录_Spring Security 实战干货:实现自定义退出登录...
  13. 8_python基础—高级变量类型(字符串、列表、元组、字典、集合)
  14. java的队列和栈_java实现队列和栈
  15. Shell 单行注释与多行注释
  16. 计算机专业毕业设计中期考核表,研究生中期考核表导师评语
  17. HTTP 错误 403.1 - 禁止访问:执行访问被拒绝
  18. mysql 序列自增长 恢复到1_MySQL查询结果另外自带一列自增序列号
  19. 问题原因及解决办法:realloc(): invalid next size
  20. 前端安全之常见漏洞及防御

热门文章

  1. 计组之数据运算:5、加减运算与溢出判断
  2. 数据结构之顺序循环队列
  3. Python 3.X 调用多线程C模块,并在C模块中回调python函数的示例
  4. 浅析libcurl多线程安全问题
  5. C/C++编程操作Redis数据库,hiredis包装redis数据库操作接口及测试(增删改查与连接)
  6. CentOS64位下python2.6升级到2.7的详细教程
  7. c# 轻量级ORM框架 实现(一)
  8. [JZOJ 5911] [NOIP2018模拟10.18] Travel 解题报告 (期望+树形DP)
  9. WinForm 之 程序退出
  10. Android_bug之Default Activity not found