赞
踩
队列的概念:
队列(简称作队,Queue)也是一种特殊的线性表,队列的数据元素以及数据元素间的逻辑关系和线性表完全相同,其差别是线性表允许在任意位置插入和删除,而队列只允许在其一端进行插入操作在其另一端进行删除操作。
队列中允许进行插入操作的一端称为队尾,允许进行删除操作的一端称为队头。队列的插入操作通常称作入队列,队列的删除操作通常称作出队列。
下图是一个依次向队列中插入数据元素a0,a1,...,an-1后的示意图:
上图中,a0是当前 队头数据元素,an-1是当前 队尾数据元素。
为了避免当只有一个元素时,对头和队尾重合使得处理变得麻烦,所以引入两个指针:front指针指向队头元素,rear指针指向队尾元素的下一个位置,这样的话,当front指针等于rear时,此队列不是还剩一个元素,而是空队列。
顺序队列 队列的顺序存储结构称为顺序队列,顺序队列实际上是运算受限的顺序表,和顺序表一样,顺序队列也是必须用一个数组来存放当前队列中的元素。由于队列的队头和队尾的位置是变化的,因而要设两个指针和分别指示队头和队尾元素在队列中的位置。
顺序队列中的溢出现象:
上图中,front指针指向队头元素,rear指针指向队尾元素的下一个位置。
图(d)中b、c、d出队后,front指针指向元素e,rear指针在数组外面。假设这个队列的总个数不超过5个,但目前如果接着入队的话,因数组末尾元素已经被占用,再向后加就会产生数组越界的错误,可实际上队列在下标为0、1、2、3、4的地方还是空闲的,我们把这种现象叫做“假溢出”——也叫假上溢。
下溢:队列为空时,做出队操作产生的溢出现象。
真上溢:当队列满时,做入队操作产生的空间溢出现象。
顺序队列的基本操作
入队时:将新元素插入rear所指的位置,并将rear+1。
出队时:删除front所指的元素,并将front+1。
所以解决假溢出的办法就是后面满了,就再从头开始,也就是头尾相接的循环。我们把队列的这种逻辑上首尾相连的顺序存储结构称为循环队列。
如何判断循环队列究竟是空的还是满的:
现在问题又来了,我们之前说,空队列时,front指针等于rear指针,那么现在循环队列满的时候,也是front等于rear,那么如何判断循环队列究竟是空的还是满的?有如下办法:
办法1:设置一个标志位flag。初始时置flag=0;每当入队列操作成功就置flag=1;每当出队列操作成功就置flag=0。则队列空的判断条件为:rear == front && flag==0;队列满的判断条件为:rear = = front && flag= =1。
办法2:保留一个元素的存储空间。此时,队列满时的判断条件为 (rear + 1) % maxSize == front;队列空的判断条件还是front == rear。
办法3:设计一个计数器count,统计队列中的元素个数。此时,队列满的判断条件为:count > 0 && rear == front ;队列空的判断条件为count == 0。
我们在接下来的代码中采用方法2来实现。
CirQueue.h 头文件
- #include<iostream>
- #include<cassert>
- using namespace std;
- #ifndef TT_CIR_QUEUE_H
- #define TT_CIR_QUEUE_H
- namespace tt
- {
- class CirQueue
- {
- public:
- using ElemType = int;
- using Status = void;
- enum State
- {
- TT_ERROR = 0,
- TT_OK = 1
- };
- public:
- CirQueue(ElemType INI_SIZE); //初始化队列
- ~CirQueue();
- ElemType isEmpty()const; //判断队列是否为空。
- ElemType isFull()const; //确定队列是否满了
-
- ElemType clear(); //将队列清空
- ElemType getHead(ElemType &elemOut); //若队列存在且非空,用elem返回队列的队头元素
- ElemType insert(ElemType elem); //若队列存在,插入新元素elem到队列中并成为队尾元素。
- ElemType remove(ElemType &elemOut);// 删除队列中的队头元素,并用elem返回。
-
- ElemType destroy(); //若队列存在,则销毁它
- Status getLength()const; //返回队列中当前元素的个数。
- Status show(); //显示队列中的所有元素
- private:
- ElemType *m_data; //数据域
- ElemType m_front; //指向队头元素
- ElemType m_rear; //指向队尾元素的下一个位置
- ElemType m_queueSize; //队列的最大容量
- };
- inline CirQueue::ElemType CirQueue::isEmpty()const //判断队列是否为空
- {
- return (m_front == m_rear);
- }
- inline CirQueue::Status CirQueue::getLength()const //返回队列中当前元素的个数
- {
- cout<< "当前队列中的元素个数为:" << (m_rear - m_front + m_queueSize) % m_queueSize << endl;
- }
- inline CirQueue::ElemType CirQueue::clear() //将队列清空
- {
- m_front = m_rear = 0;
- return TT_OK;
- }
- inline CirQueue::ElemType CirQueue::isFull()const //确定队列是否满了
- {
- return (m_rear + 1) % m_queueSize == m_front;
- }
- }
- #endif //TT_CIR_QUEUE_H
testCirQueue.cpp 源文件
- #include"CirQueue.h"
-
- namespace tt
- {
- CirQueue::CirQueue(ElemType INI_SIZE)
- {
- assert(INI_SIZE != 0);
- m_data = new int[INI_SIZE];
- assert(m_data != nullptr);
- m_queueSize = INI_SIZE; //把队列的初始化的最大容量赋值给成员数据
- m_front = m_rear = 0; //m_front等于m_rear 就是空队列
- cout << "*********** 循环队列初始化成功! **************" << endl;
- }
- CirQueue::~CirQueue()
- {
- this->destroy();
- }
- CirQueue::ElemType CirQueue::insert(ElemType elem) //插入元素致队列的尾部
- {
- if (((m_rear + 1) % m_queueSize) == m_front)//判断队列满的情况
- {
- return TT_ERROR;
- }
- m_data[m_rear] = elem; //将元素elem 添加到队列的末尾
- m_rear = (m_rear + 1) % m_queueSize; //尾指针应以此种方式加1,才会实现循环队列, 若到末尾转到数组的头部
- return TT_OK;
- }
- CirQueue::ElemType CirQueue::remove(ElemType &elemOut) //删除队列的队头元素
- {
- if (m_front == m_rear) //判断循环队列是否为空
- {
- return TT_ERROR;
- }
- elemOut = m_data[m_front]; //将对头元素赋给elem返回
- m_front = (m_front + 1) % m_queueSize; //m_front指针向后移动一位,若到最后则转到数组头部
- return TT_OK;
- }
- CirQueue::ElemType CirQueue::getHead(ElemType &elemOut) //若队列存在且非空,用elem返回队列的队头元素
- {
- if (m_front == m_rear) //判断循环队列是否为空
- {
- return TT_ERROR;
- }
- elemOut = m_data[m_front]; //把队头元素用elem返回
- return TT_OK;
- }
-
- CirQueue::ElemType CirQueue::destroy() //若队列存在,则销毁它
- {
- delete[] m_data;
- m_data = nullptr;
- m_front = m_rear = m_queueSize = 0;
- return ((!m_data) && (m_front == m_rear == m_queueSize == 0)); //多一个判断看队列是否被销毁
- }
- CirQueue::Status CirQueue::show() //显示队列的所有元素
- {
- if (m_front == m_rear)
- {
- cout << "错误,此队列中没有数据或者队列没有建立,无法显示!" << endl;
- }
- else
- {
- auto count = (m_rear - m_front + m_queueSize) % m_queueSize; //一个临时变量存储该队列的元素个数
- cout << "队列从队头至队尾内容依次为:";
- for (size_t i = m_front; i < m_front + count; ++i)
- {
- cout << m_data[i] << ' ';
- }
- cout << endl;
- }
- }
- }
-
- //测试循环队列的功能
- void testCirQueue()
- {
- int allocMemory(0);
- cout << "请输入队列初始化的最大容量:";
- cin >> allocMemory;
- tt::CirQueue myCirQueue(allocMemory); //初始化一个队列
- while (true)
- {
- {
- cout << ("\n***************************************************") << endl
- << "*************** 循环队列的基本功能展示 **************" << endl
- << "*******************************************************" << endl
- << "************** 选择1—— 数据进队列尾. ************" << endl
- << "************** 选择2—— 删除队列头元素. ************" << endl
- << "*************** 选择3—— 显示队列头元素. ************" << endl
- << "*************** 选择4—— 判断队列是否为空. ************" << endl
- << "*************** 选择5—— 判断队列是否满了. ************" << endl
- << "***************************************************************" << endl
- << "*************** 选择6—— 显示队列的元素个数. *************" << endl
- << "*************** 选择7—— 清空队列. *************" << endl
- << "**************** 选择8—— 销毁队列. *************" << endl
- << "**************** 选择9—— 显示队列中的所有元素. ***********" << endl
- << "**************** 选择10—— 清屏. *************" << endl
- << "**************** 选择0—— 退出程序! *************" << endl
- << "***************************************************************" << endl
- << "***************************************************************" << endl;
- }
- cout << "\n***************** 请输入你想要使用的队列功能的序号 ***************" << endl;
- cout << "请输入你的选择:";
- int userChoice(0);
- cin >> userChoice;
- if (!userChoice)
- {
- cout << "程序已退出,感谢您的使用!" << "\n" << endl;
- break;
- }
-
- switch (userChoice)
- {
- case 1:
- {
- int pushDatas(0);
- cout << "请输入想要添加的数据:";
- cin >> pushDatas;
- if (myCirQueue.insert(pushDatas)) //进队列
- {
- cout << "数据" << pushDatas << "成功进入队列中!" << endl;
- myCirQueue.getLength();
- myCirQueue.show(); //显示所有元素
- }
- else
- cout << "目前队列已满, 数据" << pushDatas << "进入失败!" << endl;
- break;
- }
- case 2:
- {
- int popDatas(0);
- if (myCirQueue.remove(popDatas)) //删除队列头元素
- {
- cout << "数据" << popDatas << "从队列中成功删除!" << endl;
- myCirQueue.getLength();
- myCirQueue.show();
- }
- else
- {
- cout << "目前队列为空, 数据" << popDatas << "删除失败!" << endl;
- myCirQueue.getLength();
- }
- break;
- }
- case 3:
- {
- int disHead(0);
- if (myCirQueue.getHead(disHead)) //获取队头元素
- {
- cout << "队列头元素为:" << disHead << endl;
- myCirQueue.getLength();
- myCirQueue.show();
- }
- else
- {
- cout << "目前队列为空, 数据" << disHead << "获取失败!" << endl;
- myCirQueue.getLength();
- }
- break;
- }
- case 4:
- if (myCirQueue.isEmpty()) //判断队列是否空
- {
- cout << "队列为空,或者队列尚未建立!" << endl;
- myCirQueue.getLength();
- }
- else
- {
- cout << "队列非空!" << endl;
- myCirQueue.getLength();
- myCirQueue.show();
- }
- break;
- case 5:
- if (myCirQueue.isFull()) //判断队列是否满
- {
- cout << "目前队列已满,不能再添加数据了!" << endl;
- myCirQueue.getLength();
- myCirQueue.show();
- }
- else
- {
- cout << "目前队列不满,还可以继续输入数据进栈!" << "\n" << endl;
- myCirQueue.getLength();
- myCirQueue.show();
- }
- break;
- case 6:
- myCirQueue.getLength(); //显示队列的元素个数
- myCirQueue.show();
- break;
-
- case 7:
- if (myCirQueue.clear())
- {
- cout << "队列已清空!" << endl;
- myCirQueue.getLength();
- }
- else
- {
- cout << "队列清空失败!" << endl;
- myCirQueue.getLength();
- myCirQueue.show();
- }
- break;
- case 8:
- {
- cout << "你确定要销毁一个队列吗?(若销毁请输入输入(Y/y))";
- char yesOrNo;
- cin >> yesOrNo;
- if ((yesOrNo == 'Y') || (yesOrNo == 'y'))
- {
- if (myCirQueue.destroy())
- {
- cout << "队列已被销毁!" << endl;
- }
- else
- cout << "队列销毁失败!" << endl;
- }
- break;
- }
- case 9:
- myCirQueue.getLength();
- myCirQueue.show();
- break;
- case 10:
- system("cls");
- cout << "屏幕已经清屏,可以重新输入!" << "\n" << endl;
- break;
- default:
- cout << "输入的序号不正确,请重新输入!" << "\n" << endl;
- }
- }
- }
- int main()
- {
- testCirQueue();
- system("pause");
- return 0;
- }
C# 代码实现的循环队列:
- namespace DateStructure
- {
- interface IQueue
- {
- void CreateQueue(params int[] arrElem);
- void clear();
- bool isEmpty();
- void EnQueue(int insertElem);
- int DeQueue();
- int getLength();
- void show();
- }
-
- class CirQueue : IQueue
- {
- private int[] m_data;
- private int m_front; // 循环队列队头指针
- private int m_rear; // 循环队列尾指针
- private int m_queueMaxLength;
- private int m_queueCurrentLength;
- public CirQueue(int maxSize)
- {
- Debug.Assert(maxSize > 0, "不能分配小于1的数组!");
- m_data = new int[maxSize];
- Debug.Assert(m_data != null, "初始化时,内存分配失败!");
- m_queueMaxLength = maxSize;
- m_front = m_rear = m_queueCurrentLength = 0;
- }
-
- public void CreateQueue(params int[] arrElem)
- {
- // arrElem.Length 不能等于 m_queueMaxLength,否则但添加元素时,会出现bug
- if ((arrElem != null) && (arrElem.Length != 0) && arrElem.Length < m_queueMaxLength)
- {
- m_rear = m_queueCurrentLength = arrElem.Length;
- for (int i = 0; i != m_queueCurrentLength; ++i)
- {
- m_data[i] = arrElem[i];
- }
- }
- else
- {
- throw new ArgumentException("循环队列整表创建失败!");
- }
- }
- public void clear()
- {
- m_front = m_rear = m_queueCurrentLength = 0;
- }
-
-
-
- public int DeQueue()
- {
- if (isEmpty() == true)
- {
- return -1;
- }
- int removeElem = m_data[m_front];
- m_front = (m_front + 1) % m_queueMaxLength;
- --m_queueCurrentLength;
- return removeElem;
- }
-
- public void EnQueue(int insertElem)
- {
- if ((m_rear + 1) % m_queueMaxLength == m_front)
- {
- throw new ArgumentException("当前循环队列已满,无法添加元素!");
- }
- m_data[m_rear] = insertElem;
- m_rear = (m_rear + 1) % m_queueMaxLength;
- ++m_queueCurrentLength;
- }
-
- public int getLength()
- {
- return m_queueCurrentLength;
- }
-
- public bool isEmpty()
- {
- return ((m_queueCurrentLength == 0) && (m_rear == m_front));
- }
- public void show()
- {
- if(m_queueCurrentLength == 0)
- {
- WriteLine("该循环队列中没有元素,无法输出!");
- return;
- }
- int index = m_front;
- WriteLine("输出链队列中的所有元素:");
- do
- {
- Write($"{m_data[index]},");
- index = (index + 1) % m_queueMaxLength;
- } while (index != m_rear);
- WriteLine();
- }
- }
- class Program
- {
- static void Main(string[] args)
- {
- WriteLine("输入循环队列的最大容量:");
- int sizeCapacity = Convert.ToInt32(Console.ReadLine());
- var myQueue = new CirQueue(sizeCapacity);
-
- const int arraySize = 5;
- int[] myIntArray = new int[arraySize] { 141, 11, 24, 347, 45 };
- myQueue.CreateQueue(myIntArray);
- myQueue.show();
-
- WriteLine("请输入你想插入的元素值:");
- int pushElem = Convert.ToInt32(Console.ReadLine());
- myQueue.EnQueue(pushElem);
- myQueue.show();
-
- int removeElem = myQueue.DeQueue();
- if (removeElem >= 0)
- {
- WriteLine($"被删除的元素为:{removeElem}");
- myQueue.show();
-
- }
- else
- {
- WriteLine("当前循环队列是空的,没有元素可以删除!");
- }
-
- if (myQueue.isEmpty())
- {
- WriteLine("当前的循环队列为空!");
- }
- else
- WriteLine("当前的循环队列非空!");
- WriteLine($"\n获取当前循环队列的总个数:{myQueue.getLength()}");
- myQueue.clear();
- WriteLine($"获取当前循环队列的总个数:{myQueue.getLength()}");
-
- }
-
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。