瞎折腾成功:尝试的用c++编了一个队列,用到了模板还有重载,开心
#include<iostream>
#include<cstring>
using namespace std;
template<class T> //保证这个队列的实用性所以用模板
struct quenode{ //这只是一个节点所以可以用结构体
T nodedate;
quenode *next;
};
template<class T>
class queue{
protected:
int quesize;//队列的长度
quenode<T>*head;//头结点
quenode<T>*tail;//尾节点
bool allocateerror;//布尔类型判断0或1用来判断是否队列已经满了
queue ©(queue &q);
public:
queue();//普通的构造函数
queue(queue &q)//类似于拷贝构造函数
{
head=NULL;
tail=NULL;
copy(q);
}
~queue()
{
clearque();
}
bool getallocateerror()
{return allocateerror;}
void push(T &);
bool pop(T &);
bool isempty()
{return (quesize==0)?true:false;}
void clearque();
queue &operator=(queue &q)//重载赋值运算符
{copy(q);return *this;}
};
template<typename T>//定义构造函数
queue<T>::queue()
{
quesize=0;
allocateerror=false;
head=NULL;
tail=NULL;
}
template<typename T>
queue<T>&queue<T>::copy(queue<T>&que)//拷贝函数
{
quenode<T> *p,*q,*r;
if(head)
clearque();
quesize=que.quesize;
allocateerror=false;
head=NULL;
tail=NULL;
/*先判断原队列是否为空,若不为空则清空该队列*/
if(!que.head)//判断要拷贝的队列是否为空,若为空则直接将清空好的原队列返回
return *this;
head=new quenode<T>;//为原队列的头结点分配存储空间
if(!head)//如果头结点不能分配存储空间则说明该队列不能存储,即还没存就满了
{allocateerror=true;return *this;}
head->nodedate=que.head->nodedate;
head->next=NULL;
tail=head;
r=NULL;
p=head;//p指向当前队列的头
q=que.head->next;//q指针指向当前队列的第二个节点
while(q)//循环为后续节点赋值
{
r=new quenode<T>;
if(!r)
{allocateerror=true;return *this;}
r->nodedate=q->nodedate;
r->next=NULL;
p->next=r;
tail=r;
p=p->next;
q=q->next;
//类似于为链表的赋值操作
}
return *this;
}
template<class T>
void queue<T>::push(T &x)//向队尾插入元素
{
quenode<T> *p;
p=new quenode<T>;
if(!p)
{
allocateerror=true;
return;
}
//建立p节点并为它赋值,考虑到了赋值失败
p->nodedate=x;//把要插入的元素赋给p的数据域
if(tail)//判断尾节点是否为空就是判断整个队列是否为空
{
p->next=NULL;
tail->next=p;
tail=p;
}
else//为空的话就让p成为这个队列里面唯一的节点
{
p->next=NULL;
tail=p;
head=p;
}
quesize++;//插入元素的话队列的长度一定会发生变化
}
template<class T>
bool queue<T>::pop(T &x)//从对列的头取一节点,取到x上
{
quenode<T> *p;
if(head)//判断队列是否为非空
{
x=head->nodedate;//非空时将队头的数据内容赋给x
p=head;//将取出的节点地址赋值给p,方便后面删除
head=head->next;
if(head==NULL)
tail=NULL;
delete p;//释放p所指向的地址的内存
quesize--;//提取元素则必定会是队列的长度减小
return true;
}
return false;
}
template<class T>
void queue<T>::clearque()//清空队列的函数
{
T p;
allocateerror=false;
while(pop(p));//循环提取第一个节点,把队列里所有的元素都取出来
head=tail=NULL;
}
/*关于队列的函数在这里就全部结束了,下面进行实例*/
class staff{
public:
char name[80];
int age;
float salary;
char sex[8];
void assign(char *name,int age,float salary,char *sex)
{
strcpy(staff::name,name);
staff::age=age;
staff::salary=salary;
strcpy(staff::sex,sex);
}
void print()
{printf("%-10s%-6d%-10.2f%-8s\n",name,age,salary,sex);}
};
void viewque(queue<staff>&que)
{
int i=1;
staff p;
queue<staff>quecopy(que);
system("cls");
while(quecopy.pop(p))
{
printf("%2d:",i++);
p.print();
}
}
int main()
{
queue<staff>que;
staff p;
p.assign("caopneg",20,1500,"male");
que.push(p);
p.assign("xiubi",20,222,"female");
que.push(p);
viewque(que);
return 0;
}
感觉队列和链表挺相似的,操作就是建立节点,删除节点,当然队列还不用查找节点,只要把节点往队列后面塞,或者把节点从头那里拿出来。
当然,队列里面有些函数还可以重复利用:
1.拷贝函数还可以变成拷贝构造函数。
2.取头结点的函数可以用作队列删除函数。
还有一些要注意的:
1.每次分配空间后要检查有没有分配成功。
2.取出了头结点,记得把头结点的地址释放。
3.在操作队列之前都要最好判断一下队列是否为空。
4.塞一个节点或取出一个节点都会是队列的长度发生变化,记得要改一下quesize。
最后,我还是个才上大一的学生,刚刚才学c++,平时喜欢自己在图书馆里看书琢磨,有些内容了解的也不是特别好,所以可能编的代码不是很实用或理解上存在问题,这个我是非常欢迎指出来的。还有对于c++或是其他与计算及有关的东西而言,我觉得还是多去折腾折腾较好,就像我最经折腾了好久Atom这个软件,按着百度上的步骤一步一步来都搞不定,然后我就自己折腾,下载MinGM装gcc,配路径,然后再在Atom中找插件,虽然花了很多冤枉时间,但比一直用dev-c++的那个我已经懂了不少东西了,最关键的是瞎折腾是想了解新东西的表现而且总会学到一些书本上没有的东西,那么大家就一起加油吧!