模板参数--实现容器适配器,栈和队列

我们知道数据结构中栈和队列的实现可以用顺序表或者链表来实现
那么再模板的基础上,我们来实现一个容器适配器


 
 
 
  
#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泛型来保持统一
//这样的话,当你定义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;}
//完


猜你喜欢

转载自blog.csdn.net/misszhoudandan/article/details/80294354