双端队列:相比循环队列来说,既可以取队头元素,又可以取队尾元素;可以从队头出队,也可以从队头进队;可以从队尾进队,也可以从队尾出队。
所以本文用继承循环队列的方式来实现双端队列:
1.循环队列(SeqQueue.h):
# include<iostream>
# include<assert.h>
using namespace std;
class SeqQueue{ //循环队列
private:
int* elements; //存放队列元素的数组
int rear,front; //队尾指针和对头指针
int maxSize; //队列可容纳的最大元素个数
public:
SeqQueue(int sz); //构造函数
~ SeqQueue(){ delete[]elements;} //析构函数
bool EnQueue(const int& x); //进队函数
bool DeQueue(int& x); //出队函数
void makeEmpty(){front=rear=0;} //把队置空
bool isEmpty(){return (front==rear)?true:false;} //判断队空
bool isFull(){return ((rear+1)%maxSize==front)?true:false;} //判断队满
int getSize(){return (rear-front+maxSize)%maxSize;} //求队中元素个数
int& getFront(){return front;} //取队头下标
int& getRear(){return rear;} //取队尾下标
int& getMaxSize(){return maxSize;} //取maxSize
int*& getElements( ){return elements;} //取数组指针
};
SeqQueue::SeqQueue(int sz):rear(0),front(0),maxSize(sz){
elements=new int[maxSize];
assert(elements!=NULL); //断言机制:如果不满足括号内条件将终止程序的执行
}
bool SeqQueue::EnQueue(const int& x){
if(isFull()) return false;
else
elements[rear]=x;
rear=(rear+1)%maxSize; //加一再取余是为了rear指向队列最后一个元素(下标maxSize-1),再进一下标就到了0
return true;
}
bool SeqQueue::DeQueue(int& x){
if(isEmpty()) return false;
else
x=elements[front];
front=(front+1)%maxSize;
return true;
}
2.双端队列(SeqDeque.h):继承了SeqQueue类
# include"SeqQueue.h"
# include<iostream>
using namespace std;
class SeqDeque:public SeqQueue{ //双端循环队列:公有继承循环队列
public:
SeqDeque(int sz):SeqQueue(sz){} //构造函数:调用了SeqQueue的构造函数
~SeqDeque(){ //析构函数
delete[]getElements();
}
bool getTail(int& x); //新增取队尾函数
bool EnQueueHead(const int& x); //新增从队头进队函数
bool DeQueueTail(int& x); //新增从队尾出队函数
friend ostream& operator<<(ostream& ostr,SeqDeque& D); //输出运算符重载
};
bool SeqDeque::getTail(int& x){
//SeqDeQueue继承了SeqQueue的私有数据成员,但是没有访问权限,所以通过SeqQueue的共有函数来访问
if(isEmpty()) return false;
else{
x=getElements()[(getRear()-1+getMaxSize())%getMaxSize()];
return true;
}
}
bool SeqDeque::EnQueueHead(const int& x){
if(isFull()) return false;
else{
getFront()=(getFront()-1+getMaxSize())%getMaxSize();
getElements()[getFront()]=x;
return true;
}
}
bool SeqDeque::DeQueueTail(int& x){
if(isEmpty()) return false;
else{
getRear()=(getRear()-1+getMaxSize())%getMaxSize();
x=getElements()[getRear()];
return true;
}
}
ostream& operator<<(ostream& ostr,SeqDeque& D){
ostr<<"front="<<D.getFront()<<" "<<"rear="<<D.getRear()<<endl;
for(int i=D.getFront();i!=D.getRear();i=(i+1)%D.getMaxSize())
ostr<<i+1<<": "<<D.getElements()[i]<<endl;
return ostr;
}
3.主函数(main.cpp):
# include"SeqDeque.h"
# include<iostream>
using namespace std;
int main (){
int a,n=5,value;
SeqDeque D(10);
cout<<"please enter the date into Queue"<<endl;
while(n--){
cin>>a;
D.EnQueue(a);
}
cout<<D<<endl;
D.DeQueueTail(value);
D.EnQueueHead(value);
cout<<D<<endl;
cout<<"队头元素:"<<D.getElements()[D.getFront()]<<endl;
D.getTail(value);
cout<<"队尾元素:"<<value<<endl;
system("pause");
return 0;
}
4.运行结果:
5.心得:
之前想用继承的时候老是出错:百度和发帖都没有解决问题,整个人有点浮躁。最后没办法了,翻了一下大一的旧课本才解决了问题。
问题主要出在:
- 派生类构造函数的实现方法(构造函数是不能被继承的)。
- 还有既然是为了减少代码的重复使用,那么在派生类中基类已经存在的数据成员和功能相同的函数成员就不要再出现了,它们本来就是属于派生类的,虽然派生类中没写出。在注意访问权限的同时可直接被派生类对象调用。