栈的实现及应用

1.栈定义
栈又称堆栈,是一种运算受限的线性表,限制是仅仅允许在表的另外一端进行插入和删除运算。
2.特点
后进先出、cpu缓存利用率相对较高、不允许随意访问
3.实现方式
栈有两种实现方式,一种是顺序存储,和数组类似。一种是链式存储,和单链表类似。
(这是在2013编译器下)
栈里面有以下几种函数:

void Push(const T& x);
void Pop();
T& Top();
bool Empty();
size_t Size();

栈函数定义和实现:

template<class T>
class Stack
{
public:
    Stack()//构造函数
        :_a(NULL)
        , _size(0)
        , _capacity(0)
    {}
    Stack(const Stack<T> & s)//拷贝构造函数
    {
        _capacity = s._capacity;
        _size = s._size;
        _a = new T[_capacity];
        for (size_t i = 0; i < _size; i++)//非内置类型例如String类型时,用for循环赋值
        {
            _a[i] = s._a[i];
        }
    }
    Stack<T>& operator=(const Stack<T> &s)//赋值运算符重载
    {
        if (_capacity < s._capacity)
        {
            _capacity = s._capacity;
            _a = new T[_capacity];
        }
        _size = s._size;
        for (size_t i = 0; i < _size; i++)
        {
            _a[i] = s._a[i];
        }
        return *this;
    }
    ~Stack()//析构函数
    {
        if (_a)
        {
            delete _a;
        }
    }
    //接口函数实现
    void Push(const T& x)//入栈,插入数据
    {
        _CheckCapacity();
        _a[_size++] = x;
    }
    void Pop()//删除数据
    {
        assert(_size);
        --_size;
    }
    T& Top()//返回栈顶元素
    {
        assert(_size);
        return _a[_size - 1];
    }
    bool Empty()//判空
    {
        return _a == 0;
    }
    size_t Size()//元素个数
    {
        return _size;
    }

protected:
    void _CheckCapacity()//判断容量
    {
        if (_size >= _capacity)
        {
            T* tmp = new T[_capacity * 2 + 10];
            for (size_t i = 0; i < _size; i++)
            {
                tmp[i] = _a[i];
            }
            delete _a;
            _a = tmp;
            _capacity = _capacity * 2 + 10;
        }
    }
protected:
    T * _a;//存储数据的指针
    size_t _size;//存储数据个数
    size_t _capacity;//容量
};

测试函数:

void TestStack()
{
    Stack<int> s;
    s.Push(1);
    s.Push(2);
    s.Push(3);
    s.Push(4);
    cout << s.Size() << endl;
    s.Pop();
    cout << s.Size() << endl;
    cout << s.Empty() << endl;
    cout << s.Top() << endl;
}

结果:
这里写图片描述

关于栈的一个小应用,其中有一个后缀表达式的计算,也叫做逆波兰表达式,参加运算的操作数总在操作符前面。
后缀表达式求值过程:顺序扫描表达式的每一项,如果该项是操作数,则将其压入栈中,如果是操作符,则从栈中退出两个操作数,形成运算指令,并将运算结果再压入栈中。
下面简单的模拟实现一下后缀表达式:

#include<iostream>
using namespace std;
#include<assert.h>
#include <stack>  

enum Type             
{
    OP_SYMBOL,  //操作符   
    OP_NUM,     //操作数    
    ADD,
    SUB,
    MUL,
    DIV,
};

struct Cell      //cell单元存储里面的枚举类型和所push的操作数  
{
    Type _type;
    int _value;
};

int CountPRN(Cell* rpn, size_t n)   
{
    assert(rpn);
    stack<int> s;                        
    for (size_t i = 0; i < n; ++i)
    {
        if (rpn[i]._type == OP_NUM) //若数组中为操作数则压栈      
        {
            s.push(rpn[i]._value);        
        }
        else if (rpn[i]._type == OP_SYMBOL)//若为操作符则出栈运算
        {
            int right = s.top(); 
            s.pop();
            int left = s.top();
            s.pop();
            switch (rpn[i]._value)     
            {
            case ADD:
                s.push(left + right);
                break;
            case SUB:
                s.push(left - right);
                break;
            case MUL:
                s.push(left * right);
                break;
            case DIV:
                s.push(left / right);
                break;
            default:
                assert(false);
            }
        }
    }
    return s.top();                               
}
void TestRPN()
{
    Cell RPN[] = {
                    { OP_NUM, 8 },
                    { OP_NUM, 2 },
                    { OP_SYMBOL, MUL }
                };
    cout << CountPRN(RPN, sizeof(RPN) / sizeof(RPN[0]));
}

int main()
{
    TestRPN();
    system("pause");
    return 0;
}

结果:这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值