数据结构-环形队列-队列模板实现-c++代码
一、队列(FIFO-first in first out)
- 分类:
- 普通队列: 先进先出,读取时有两种:一种是指针移动向下读取;一种是每读取一个元素,后面的所有元素自动向前移动一个位置。
- 这两种办法都有缺点。第一种会造成出栈后的数据的位置没有被重新利用,内存浪费。第二种是每次读出一个元素,后面所有元素都前进移动,效率低下。
- 环形队列: 预先设定环形队列可容纳值的大小,分头指针和尾指针指示队列的头和尾。存储时存在尾指针位置,然后尾指针加一。读取时读头指针位置,头指针加一。这样所有的空间可以循环利用。利用判空或判满函数来决定队列是否还有元素或者队列是否已满。
- 缺点是队列大小不可变,如果队列满了,就不能再加入新元素。但是效率高,空间利用同样高效。
- 普通队列: 先进先出,读取时有两种:一种是指针移动向下读取;一种是每读取一个元素,后面的所有元素自动向前移动一个位置。
- Note that:
- 新建类对象在创建该类型的数组时,为防止报错,需要给构造函数里的元素赋初值
环形队列实现代码
//队列模板实现.h文件
#pragma once
#include<iostream>
using namespace std;
template<class T>
class Myqueue
{
public:
Myqueue(int num);//构建队列大小
void addIngre(T m);//增加元素
void deleIngre();//删除元素
int IngreNum();//返回当前队列元素个数
bool queueFull();//判断满
void clearIngre();//清空队列
bool queueEmpty();//判空队列
void queueTraverse();//遍历元素
~Myqueue();//析构
private:
int m_iNum; //队列元素个数
T* m_tArray;//数组
int m_iHead;//头指针位置
int m_iTail;//尾指针位置
int m_iSize;//队列大小
};
template<class T>
Myqueue<T>::Myqueue(int num)
{
clearIngre();
m_iSize = num;
m_tArray = new T[m_iSize];
}
template<class T>
Myqueue<T>::~Myqueue()
{
delete[]m_tArray;
m_tArray = NULL;
}
template<class T>
void Myqueue<T>::addIngre(T m)//增加元素
{
if (!queueFull())
{
m_iNum++;
m_iTail = m_iTail % m_iSize;
m_tArray[m_iTail] = m;
m_iTail++;
}
else
{
cout << "Can not add any more ingredients!" << endl;
}
}
template<class T>
void Myqueue<T>::deleIngre()//首元素出队
{
if (!queueEmpty())
{
m_iNum--;
cout <<"被消除的首元素为:"<< m_tArray[m_iHead] << endl;
m_iHead++;
m_iHead = m_iHead % m_iSize;
}
else
{
cout << "There is no ingredient!" << endl;
}
}
template<class T>
int Myqueue<T>::IngreNum()//返回当前队列元素个数
{
cout << "当前元素个数为:" <<m_iNum<< endl;
return m_iNum;
}
template<class T>
void Myqueue<T>::clearIngre()
{
m_iNum = 0;
m_iTail = m_iHead = 0;
cout << "当前元素个数为:" << m_iNum << endl;
}//清空队列
template<class T>
bool Myqueue<T>::queueEmpty()
{
return m_iNum == 0 ? true : false;
}//判空队列
template<class T>
bool Myqueue<T>::queueFull()
{
return m_iNum == m_iSize ? true : false;
}//判断满
template<class T>
void Myqueue<T>::queueTraverse()
{
for (int i = m_iHead; i < m_iNum + m_iHead; i++)
{
i = i % m_iSize;
cout << m_tArray[i] << endl;
}
}//遍历元素
//自定义类customer的.h文件
#pragma once
#include<iostream>
using namespace std;
#include<string>
class customer
{
friend ostream& operator<<(ostream& out, customer& c)//<<重载只能用友元函数,因为与this指针无关
{
out << "Name:"<<c.name<<","<<"Age:" << c.age;
return out;//必须有返回值
}
public:
customer(string n="陈胖鹿",int a=4);//为了防止自定义类在创建数组时报错,需要赋初值。猜测是因为编译器没有初值的话不知道需要开辟多少内存出来。
~customer();
//重载<<
//重载=
customer& operator=(customer& m)
{
this->name = m.name;
this->age = m.age;
return *this;//必须返回
}
private:
string name;
int age;
};
//自定义类的.cpp文件
#include"customer.h"
customer::customer(string n, int a):name(n),age(a)
{
}
customer::~customer()
{
}
//main.cpp;Note that: 队列的模板<>内可以是任何编译器已经存在的类型如int,double,float,string等。如果想加入自定义的类,则自定义类需要重"=","<<"两个符号,本例中自定义类已经重载该两个符号
#include"Myqueue.h"
#include<string>
#include"customer.h"
int main()
{
Myqueue<customer> * p = new Myqueue<customer>(4);
customer c1("张三",43);
customer c2("张四", 44);
customer c3("张五", 46);
p->addIngre(c1);
p->addIngre(c2);
p->addIngre(c3);
p->queueTraverse();
cout << endl;
p->deleIngre();
p->deleIngre();
p->deleIngre();
p->IngreNum();
delete p;//需要删除p
p = NULL;//并将其置于安全状态
return 0;
}
Higher you climb, more view you will see.
posted on 2019-12-11 08:47 Nancy_Fighting 阅读(393) 评论(0) 编辑 收藏 举报