栈:栈是一种特殊的线型表,其插入(也称入栈或压栈)和删除(也称出栈和谈栈)操作都在表的同一端进行。这一端称为栈顶,另一端称为栈底。

其实栈就是一种被限制的线性表,栈的功能是之前线性表的子集,比如线性表能在任意地方进行插入,而栈只能在尾部进行插入。

接下来实现一个数组描述栈:
1.派生自之前的arrayList:

template<class T>
class stack
{
    public:
    virtual ~stack(){}
    virtual bool empty() const=0;
    virtual int size() const=0;
    virtual T& top()=0;
    virtual void pop()=0;
    virtual void push(const T& theElement)=0;
};

template<class T>
class derivedArrayStack:private arrayList<T>,public stack<T>
{
    public:
    derivedArrayStack(int initialCapacity=10):arrayList<T> (initialCapacity){}
    bool empty() const{return arrayList<T>::empty();}//因为对父类的const进行了重写,所以必须用作用域进行调用
    int size() const{return arrayList<T>::empty();}
    T& top()
    {if(arrayList<T>::empty()) throw stackEmpty(); return get(arrayList<T>::size()-1;)}
    void pop()
    {
        if(arrayList<T>::empty()) throw stackEmpty();erase(arrayList<T>::size()-1);//没有返回直接删了
    }
    void push(const T& theElement)
    {insert(arrayList<T>::size(),theElement;)}

};

当父类有自定义的有参构造函数,而你又没有定义无参的构造函数时,默认无参构造函数失效
子类构造函数是默认调用父类无参构造函数的,如果父类没有无参构造,你就得利用列表初始化显示调用
父类构造函数了。

派生出来的类性能低下。
2.重新写一个stack并不从arrayList派生

template<class T>
class arrayStack:public stack<T>
{
    public:
    arrayStack(int  initialCapacity=10);
    ~arrayStack(){delete [] stack;}
    bool empty() const {return stackTop==-1;}
    int size() const{return stack+1;}
    T& top()
    {
        if(stackTop==-1)
            throw stackEmpty();
        return stack[stackTop];
    }
    void pop()
    {
        if(stackTop==-1)
            throw stackEmpty();
        stack[stackTop--].~T();//注意这里是先析构在减一。
    }
    void push(const T& theElement);
    private:
    int stackTop;
    int arrayLength;
    T *stack;
};
template<class T>
arrayStack::arrayStack(int initialCapacity)
{
    if(initialCapacity<1)
    {
        ostringstream s;
        s<<"Initial capacity="<<initialCapacity<<"Must be >0";
        throw illegalParameterValue(s.str());
    }
    arrayLength=initialCapacity;
    stack=new T[arrayLength];
    stackTop=-1;
}
template<class T>
void arrayStack<T>::push(const T& theElement)
{
    if(stackTop==arrayLength-1)
    {
        changeLength1D(stack,arrayLength,2*arrayLength)//这个倍增函数我们之前已经写过了
        arrayLength*=2;
    }
    stack[++stackTop]=theElement;
}

这个构造的主要部分就是多了一个指向栈顶的int型变量,当栈为空时,栈顶指向-1,当增加一个数时,栈顶指向0,是很合理的。数据的存取都靠这个数据管理。

接下来是栈的链表实现,原理与上面一样,也是额外定义一个指向栈顶的元素。不过他的节点的next指针是指向之前的一个节点而不是之后的节点,因为它只能从后往前进行查找。

template<class T>
class linkedStack:public stack<T>
{
    public:
    linkedStack(int initialCapacity=10)
    {stackTop=NULL;stackSize=0;}
    ~linkedStack();

    bool empty()const
    {return stackSize==0;}
    int size()const{return stackSize;}
    T& top()
    {
        if(stackSize==0)
            throw stackEmpty();
        return stackTop->element;
    }
    void pop();
    void push(const T& theElement)
    {
        stackTop=new chainNode<T>(theElement,stackTop);//这个是结构体里面的构造函数,之前写过
        stackSize++;//这个地方需要注意的是,chainNode里面的next指针指向的是上一个节点而不是后一个
    }
    private:
    chainNode<T>* stackTop;
    int stackSize;
}
template<class T>
linkedStack<T>::~linkedStack()
{
    while(stackTop!=NULL)
    {
        chainNode<T>* nextNode=stackTop->next;
        delete stackTop;
        stackTop=nextNode;
    }
}

template<class T>
void linkedStack<T>::pop()
{
    if(stackSize==0)
        throw stackEmpty();

    chainNode<T>* nextNode=stackTop->next;//删除的时候通过next指针获取上一个节点的指针,然后删除当前节点
    delete stackTop;
    stackTop=nextNode;//再把上一个节点的指针赋值给stackTop指针。
    stackSize--;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值