使用模板构建泛型栈

目录

一.构造栈

使用构造函数

代码:

二.销毁栈

使用析构函数

代码

三.判空,判满

四.扩容

代码

五.入栈,出栈

代码

六.取栈顶元素

代码

代码合集

template< class T>模板

T为当前栈的数据类型

栈类型有三个属性:栈的空间大小,栈顶指针,以及用以存储元素的空间。

一.构造栈

使用构造函数

初始化栈类型的三个属性:设无任何元素的栈的栈顶指针为-1。

使用new关键字为栈申请空间大小。

new的作用:计算类型大小,malloc开辟空间,构造对象,将空间的地址返回

为了判断申请空间是否成功,需要判空。根据new的特性,我们不能直接使用nullptr去判空,因为new关键字出现异常会直接停止,系统跳出异常

代码:

Seqstack(int sz = STACK_INIT_SIZE) :_top(-1), _size{ sz }, _data{ nullptr }{
        _data = new(nothrow) T [sz];
        if (nullptr == _data) {
            exit(EXIT_FAILURE);
        }
    }

二.销毁栈

使用析构函数

因为用new关键字开辟空间,所以我们要用delete关键字收回空间并free

由于_data是一个数组,需要用delete[]去析构。

这里的构造函数和析构函数,小白认为和人的诞生死亡是相同的,可以这么简单认为。

当栈空间由系统收回后,_size空间大小变为0,栈顶指针指向最底。

代码

~Seqstack() {
        delete[]_data;
        _data = nullptr;
        _size = 0;
        _top = -1;
}

三.判空,判满

这里有任何疑问可以参考小白在数据结构处所写的栈。

int GetSize() {
        return _top + 1;
    }
    int GetCapth()  {
        return _size;
    }
    bool Empty() {
        return _top+1==0;
    }
    bool Full() {
        return _top+1==_size;
    }

四.扩容

这里注意两点:

1.开辟新数组后,新数组的长度是原来数组的2倍,而当你使用new关键字的时候,new关键字是没有将原先数组的值拷贝过去的功能,所以得使用内存函数,将内容一字节一字节拷贝过去。而原数组和新数组长度不一样,一定要注意这个,否则拷贝过去后,新数组的部分值是随机值。

如果用realloc函数就没有这么麻烦。

2.当把原先的数组拷贝完后,我们要把新开辟的数组返回给原数组,需要干的第一步就是把原先数组资源释放掉,然后把原数组里的元素删干净,并指向空,防止出现空悬指针。最后将新构建的赋值过去即可。

代码

new

bool Inc( ) {
        int newsize = STACK_INIT_SIZE * STACK_INC_SIZE;
        if (newsize <= _size)return true;
        //在这里注意 申请空间以2倍扩容
        T* newdata = new(nothrow)T [newsize];
        if (newdata == nullptr) {
            return false;
        }
        memmove(newdata, _data, sizeof(T) * GetSize());
        delete[]_data;
        _data = nullptr;
        _data = newdata;
        _size = STACK_INIT_SIZE * 2;
        return true;
    }

realloc

   bool Inc(size_t newsz)
    {
        if (newsz <= GetCapt())
        {
            return true;
        }
        T* newdata = (T*)realloc(_data, sizeof(T) * newsz);
        if (nullptr == newdata)return false;
        _data = newdata;
        _size = newsz;
        return true;
    }

五.入栈,出栈

这里没有什么难点。有问题的宝子可以去看看小白在数据结构处写的栈

代码

void Push(T val) {
        if (Full() && !Inc()) {
            return;
        }
        _data[++_top] = val;
    }
void Pop() {
        if (Empty()) {
            return;
        }
        _top--;
    }

六.取栈顶元素

这里我们使用引用将值返回,因为当函数结束后,函数所占的栈空间释放后,我们所建的栈还在,栈顶元素值仍在,所以可以使用引用去返回。

注意:引用返回:当返回的值受到函数调用结束影响,即存在僵亡值时,不能使用引用返回。不安全

同理我们也可以使用钓鱼的方式将取栈顶元素和出栈合二为一

代码

T& Top()const {
        return _data[_top];
    }
T& GetPop() {
        assert(_data != nullptr);
        return _data[_top--];
    }

代码合集

#include<iostream>
#include<cstring>
#include<assert.h>
using namespace std;
template<class T>
class Seqstack {
private:
    enum { STACK_INIT_SIZE = 10, STACK_INC_SIZE = 2 };
    T* _data;
    int _size;
    int _top;
public:
    Seqstack(int sz = STACK_INIT_SIZE) :_top(-1), _size{ sz }, _data{ nullptr }{
        _data = new(nothrow) T [sz];
        if (nullptr == _data) {
            exit(EXIT_FAILURE);
        }
    }
    ~Seqstack() {
        delete[]_data;
        _data = nullptr;
        _size = 0;
        _top = -1;
    }
    int GetSize() {
        return _top + 1;
    }
    int GetCapth()  {
        return _size;
    }
    bool Empty() {
        return _top+1==0;
    }
    bool Full() {
        return _top+1==_size;
    }
    bool Inc( ) {
        int newsize = STACK_INIT_SIZE * STACK_INC_SIZE;
        if (newsize <= _size)return true;
        //在这里注意 申请空间以2倍扩容
        T* newdata = new(nothrow)T [newsize];
        if (newdata == nullptr) {
            return false;
        }
        memmove(newdata, _data, sizeof(T) * GetSize());
        delete[]_data;
        _data = nullptr;
        _data = newdata;
        _size = STACK_INIT_SIZE * 2;
        return true;
    }
    void Push(T val) {
        if (Full() && !Inc()) {
            return;
        }
        _data[++_top] = val;
    }
    T& Top()const {
        return _data[_top];
    }
    void Pop() {
        if (Empty()) {
            return;
        }
        _top--;
    }
    T& GetPop() {
        assert(_data != nullptr);
        return _data[_top--];
    }
};
int main() {
    Seqstack<int> mys;
    for (int i = 1; i < 20; i++) {
        mys.Push(i);
    }
    int val_0 = 0;
    cout << mys.Top() << endl;
    while (!mys.Empty()) {
        val_0 = mys.GetPop();
        cout << val_0 << " ";
    }
    cout << endl;
    Seqstack<double> mys1;
    mys1.Push(12.23);
    mys1.Push(23.34);
    mys1.Push(34.45);
    mys1.Push(45.56);
    mys1.Push(67.78);
    mys1.Push(78.89); 
    mys1.Push(89.90); 
    mys1.Push(100.10);
    double val = 0.0;
    cout << mys1.Top() << endl;
    while (!mys1.Empty()) {
        val = mys1.GetPop();
        cout << val << " ";
    }
}

结果:

小白在数据结构中所写的顺序栈:Day 08顺序栈_早点打完工去睡觉的博客-CSDN博客

good good study,day day up!

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值