我们知道数据结构中栈和队列的实现可以用顺序表或者链表来实现
那么再模板的基础上,我们来实现一个容器适配器
#pragma once
#include "List.h"
#include "List.cpp"
#include "Vector.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string>
#include <iostream>
using namespace std;//template<class T,class container>
template<class T,template<class> class container=Vector>
//模板的模板参数,用于和前面的T泛型来保持统一
//并且这里Stack将其缺省值给Vector
class Stack
{
public:
void Push(const T &x);
void Pop();
bool Top(T & tmp);
size_t Size();
bool Empty();
void Display();
protected:
container<T> _con;//这里要用T来指定类型
};
//template<class T,class container>
template<class T,template<class> class container=List>
//模板的模板参数,用于和前面的T泛型来保持统一
//并且这里Queue将其缺省值给List,便于头删
class Queue
{
public:
void Push(const T &x);
void Pop();
bool Front(T &tmp);
size_t Size();
bool Empty();
void Display();
protected:
container<T> _con;
};
注意这里的内容:
//template<class T,class container>
当采用上面的这种写法时,有可能会造成这样的问题
如果出现下面的代码
Stack<int Vector<char> >
这种情况时,这种情况虽然编译器可以编译通过
但是如果将pushBack(200),对于char类型很明显就越界了
为了避免这种情况的出现,我们一般采用下面的这种方法:
template<class T,template<class> class container=Vector>
//模板的模板参数,用于和前面的T泛型来保持统一
//模板的模板参数,用于和前面的T泛型来保持统一
//这样的话,当你定义container时可以直接用
//conntainer<T> _con;
这里就是不知道为什么每次贴上去的代码好好的,之后再打开就是这样了,修改之后还是这样,好像不止我一个人是这样。
这里是完整代码:
点击打开链接
//Vector.h文件#pragma once#include <stdio.h>#include <string>#include <string.h>#include <stdlib.h>#include <assert.h>#include <iostream>using namespace std;template <class T>class Vector{public: Vector():_start(NULL),_finish(NULL),_endOfstorage(NULL) {} ~Vector() { delete []_start; _start=_finish=_endOfstorage=NULL; } size_t Size() const { return _finish-_start; } size_t Capacity() const { return _endOfstorage-_start; } Vector(const Vector<T> &v); Vector<T> operator=(const Vector<T> &v); void PushBack(const T & value); void PushFront(const T & value); void PopFront(); T & Back(); T & Front(); bool Empty(); void PopBack(); void Insert(size_t pos,const T & value); void Erase(size_t pos); void clear(); void Display();protected: T *_start; T *_finish; T *_endOfstorage; void Expend(size_t n)//扩容可以不作为接口 { if(Capacity()==0) {//最开始 n=3; } if(n>Capacity()) { size_t size=Size();//这里需要先将size保存下来 T * tmp=new T[n]; T * start=tmp; T *finish=_start; while(finish!=_finish) { *start=*finish; ++start; ++finish; }//将旧的数据先复制过去 clear();//清理掉旧的 _start=tmp; _finish=tmp+size; _endOfstorage=_start+n; } }};template <class T>Vector<T>::Vector(const Vector<T> &v):_start(NULL),_finish(NULL),_endOfstorage(NULL){ _start=new T[v.Size()]; T *start=_start; T *finish=v._start; while(finish!=v._finish) { *start=*finish; ++start; ++finish; } //将v中的数据都拷贝进去 _finish=_start+v.Size(); _endOfstorage=_finish;}template<class T>Vector<T> Vector<T>:: operator=(const Vector<T> &v){ //if(this!=&v) //{ //T *tmp=new T[v.Size()]; //T *start=tmp; //T *finish=v._start; //while(finish!=v._finish) //{ // *start=*finish; // start++; // finish++; //} //clear(); //_start=tmp; //_finish=_start+v.Size(); //_endOfstorage=_finish; //} //采用现代写法,函数结束后会自己调用析构函数 //采用传统写法 if(this!=&v) { Vector<T> tmp(v); swap(tmp._start,_start); swap(tmp._finish,_finish); swap(tmp._endOfstorage,_endOfstorage); } return *this;}template<class T>void Vector<T>::Insert(size_t pos,const T & value){ if(pos>Size()) {//Size()位置也是可以进行插入的,为了进行尾插 return; } if(Size()>=Capacity()) {//需要进行扩容 Expend(Capacity()*2); } //然后将pos位置后面的数据向后移动 T *cur=_finish;//这里采用指针的方法是为了避免pos的size_t类型的比较 while(cur!=_start+pos) { *cur=*(cur-1); --cur; } _start[pos]=value; _finish++;//完成一次插入后需要将_finish后移}template<class T>void Vector<T>:: PushBack(const T & value){//这里传参要传引用,因为value若是一个链表或者比较大的数据,传值会进行拷贝构造,代价比较大 Insert(Size(),value);}template<class T>void Vector<T>::PopBack(){ Erase(Size()-1);}template<class T>void Vector<T>::Erase(size_t pos){ if(pos>=Size()) { return; } if(Size()==0) { return; } //将pos位置开始的元素向前移动 T *cur=_start+pos+1; while(cur!=_finish) { *(cur-1)=*(cur); cur++; } --_finish;//删除一个元素之后需要将_finish向前移动}template<class T>void Vector<T>::PushFront(const T & value){ Insert(0,value);}template<class T>void Vector<T>::PopFront(){ Erase(0);}template<class T>T & Vector<T>::Back()//这里没有做是否为空的判断,是因为这个接口是为了给后面的适配器用的{ return _start[Size()-1];}template<class T>T & Vector<T>::Front(){ return _start[0];}template<class T>bool Vector<T>::Empty(){ return _finish==_start;}template<class T>void Vector<T>::clear(){ delete[] _start; _start=_finish=_endOfstorage=NULL;}template<class T>void Vector<T>::Display(){ if(Size()==0) { return; } T *cur=_start; while(cur!=_finish) { cout<<*cur<<" "; ++cur; } cout<<endl;}
//List.h文件
#pragma once#include <stdio.h>#include <assert.h>#include <stdlib.h>#include <string>#include <iostream>using namespace std;
template <class T>struct Node{ T _data; Node *_next; Node *_prev; Node(const T &x):_data(x),_next(NULL),_prev(NULL) {}};template <class T>class List{public: List();//这里头结点用T泛型的匿名变量来初始化 List(const List<T> &L1); List<T> & operator=(const List<T> &L1); ~List(); Node<T> * Insert( Node<T> * pos, const T& x ); void Erase(Node<T> *pos); Node<T> * PushBack( const T &x ); void PushFront(const T &x); void PopBack(); void PopFront(); size_t Size() const; bool Empty(); const T & Back()const; const T & Front()const; void Clear(); void Display();protected: Node<T> *_head;};
//List.cpp文件
#include "List.h"template <class T>
List<T>::List():_head( new Node<T>(T()))//这里头结点用T泛型的匿名变量来初始化 { _head->_next=_head; _head->_prev=_head; }template <class T> List<T>::List(const List<T> &L1):_head(new Node<T>(T())) { _head->_next=_head; _head->_prev=_head; Node<T> *cur=L1._head->_next; while(cur!=L1._head) { PushBack(cur->_data); cur=cur->_next; } }template <class T> List<T> & List<T>::operator=(const List<T> &L1) {//TODO List<T> L2(L1);//先用L1拷贝构造L2,再将L2和this交换 swap(this->_head,L2._head); //函数调用结束后会自己调析构函数来释放L2即释放旧的this指向的内容 }template <class T> List<T>::~List() { Node<T> *cur=_head->_next; while(cur!=_head) { PopBack(); cur=cur->_next; } delete _head; }template <class T> Node<T> * List<T>::Insert( Node<T> * pos, const T& x ) { assert(pos); Node<T> * new_node=new Node<T>(x); Node<T> * prev=pos->_prev;
prev->_next=new_node; new_node->_prev=prev;
new_node->_next=pos; pos->_prev=new_node; return new_node; }template <class T> void List<T>::Erase(Node<T> *pos) { assert(pos); assert(pos!=_head); Node<T> * prev=pos->_prev; Node<T> * next=pos->_next;
prev->_next=next; next->_prev=prev; delete pos; }template <class T> Node<T> * List<T>::PushBack( const T &x ) { return Insert(_head,x); }template <class T> void List<T>::PushFront(const T &x) { Insert(_head->_next,x); }template <class T> void List<T>::PopBack() { Erase(_head->_prev); }template <class T> void List<T>::PopFront() { Erase(_head->_next); }template <class T> size_t List<T>::Size() const { size_t count=0; Node<T> *cur=_head->_next; while(cur!=_head) { count++; cur=cur->_next; } return count; }template <class T> bool List<T>::Empty() { return _head->_next==_head; }template <class T> const T & List<T>::Back()const { return _head->_prev->_data; }template <class T> const T & List<T>::Front()const { return _head->_next->_data; }template <class T> void List<T>::Clear()//清理掉链表中的数据 { Node<T> *cur=_head->_next; while(cur!=_head) { PopBack(); cur=cur->_next; } _head->_next=_head; _head->_prev=_head; }template <class T>void List<T>::Display(){ Node<T> *cur=_head->_next; while(cur!=_head) { cout<<cur->_data<<" "; cur=cur->_next; } cout<<endl;}
//Container.h文件
#pragma once#include "List.h"#include "List.cpp"#include "Vector.h"#include <stdio.h>#include <stdlib.h>#include <assert.h>#include <string>#include <iostream>using namespace std;
//template<class T,class container>template<class T,template<class> class container=Vector>//模板的模板参数,用于和前面的T泛型来保持统一//并且这里Stack将其缺省值给Vectorclass Stack{public: void Push(const T &x); void Pop(); bool Top(T & tmp); size_t Size(); bool Empty(); void Display();protected: container<T> _con;//这里要用T来指定类型};//template<class T,class container>template<class T,template<class> class container=List>//模板的模板参数,用于和前面的T泛型来保持统一//并且这里Queue将其缺省值给List,便于头删class Queue{public: void Push(const T &x); void Pop(); bool Front(T &tmp); size_t Size(); bool Empty(); void Display();protected: container<T> _con;};
//Container.cpp文件
#include <iostream>#include "Container.h"
//*********以下是栈的实现************
//template<class T,class container>template<class T,template<class> class container>//当使用了模板的模板参数时,这里不可以将其缺省值列出来(类似于函数参数的缺省处理)void Stack<T,container>::Push(const T &x){ _con.PushFront(x); }
//template<class T,class container>template<class T,template<class> class container>void Stack<T,container>::Pop(){ _con.PopFront();}
//template<class T,class container>template<class T,template<class> class container>bool Stack<T,container>::Top(T & tmp){ if(_con.Empty()) { return false; } tmp=_con.Front(); return true;}
///template<class T,class container>template<class T,template<class> class container>size_t Stack<T,container>::Size(){ return _con.Size();}
//template<class T,class container>template<class T,template<class> class container>bool Stack<T,container>::Empty(){ return _con.Empty();}
//template<class T,class container>template<class T,template<class> class container>void Stack<T,container>::Display(){ _con.Display();}
//*********以下是队列的实现************
//template<class T,class container>template<class T,template<class> class container>void Queue<T,container>::Push(const T &x){ _con.PushBack(x);}
//template<class T,class container>template<class T,template<class> class container>void Queue<T,container>::Pop(){ _con.PopFront();}
//template<class T,class container>template<class T,template<class> class container>bool Queue<T,container>::Front(T &tmp){ if(Empty()) { return false; } tmp=_con.Front(); return true;}
//template<class T,class container>template<class T,template<class> class container>size_t Queue<T,container>::Size(){ return _con.Size();}
//template<class T,class container>template<class T,template<class> class container>bool Queue<T,container>::Empty(){ return _con.Empty();}
//template<class T,class container>template<class T,template<class> class container>void Queue<T,container>::Display(){ _con.Display();}
//test.cpp文件
#include "Container.h"#include "Container.cpp"
void Test_Stack(){ //Stack<int ,Vector<int> > S1; Stack<int ,Vector > S1; S1.Push(1); S1.Push(2); S1.Push(3); S1.Push(4); S1.Push(5); cout<<"显示栈中元素"<<endl; S1.Display(); //Stack<int ,Vector<int> > S2(S1);//注意这里后面的空格 Stack<int ,Vector> S2(S1);
S2.Display(); int top=0; bool ret=S2.Top(top); if(ret==0) { cout<<"栈为空"<<endl; } else { cout<<"栈顶:"<<top<<endl; } cout<<"出栈3个元素"<<endl; S2.Pop(); S2.Pop(); S2.Pop(); S2.Display();}void Test_Queue(){ //Queue<int ,List<int> > Q1; Queue<int ,List > Q1; Q1.Push(1); Q1.Push(2); Q1.Push(3); Q1.Push(4); Q1.Push(5); cout<<"显示队列元素"<<endl; Q1.Display(); //Queue<int ,List<int> > Q2(Q1); Queue<int ,List> Q2(Q1);
Q2.Display(); int top=0; bool ret=Q2.Front(top); if(ret==0) { cout<<"队列为空"<<endl; } else { cout<<"对头:"<<top<<endl; } cout<<"出队列3个元素"<<endl; Q2.Pop(); Q2.Pop(); Q2.Pop(); Q2.Display(); Q2.Pop(); Q2.Pop(); cout<<"再出队列2个元素"<<endl; ret=Q2.Front(top); if(ret==0) { cout<<"队列为空"<<endl; } else { cout<<"对头:"<<top<<endl; }}
int main(){ Test_Stack(); Test_Queue(); return 0;}
//完