数据结构-环形队列-队列模板实现-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;
}

posted on 2019-12-11 08:47  Nancy_Fighting  阅读(393)  评论(0编辑  收藏  举报

导航