C/C++数据结构之用数组实现栈

概述

要在C/C++中用数组自行实现栈,我们首先需要理解栈提供的基本操作。这些操作主要包括以下5个接口。

Push:向栈中添加一个元素。

Pop:从栈中移除顶部元素,并返回该元素。

Top:查看栈顶元素但不移除它。

IsEmpty:检查栈是否为空。

Size:获取栈中元素的数量。

实现原理

如果我们用固定大小的数组来实现栈,优点是简单、快速。但这样不够灵活,容量一开始就定死了。如果数据太多就会溢出,太少又浪费内存。为了更灵活地管理内存,我们可以使用new \[\]来动态分配数组空间,就像搭积木一样,需要多少就申请多少,甚至还可以自动扩容。

在下面栈CArrayStack的实现中,我们声明了四个成员变量,分别为:m_paData、m_nCapacity、m_nTopIndex、m_nCount。m_paData是一个动态分配的数组的地址,用来存储栈中的所有元素。m_nCapacity表示当前栈最多可以容纳多少个元素。m_nTopIndex表示当前栈顶元素的索引,也就是最后放入的那个元素的位置。m_nCount用于记录当前栈中已有的元素数量。

cpp 复制代码
class CArrayStack
{
public:
    CArrayStack();
    ~CArrayStack();

    void Push(int nValue);
    int Pop();

    int Top();
    bool IsEmpty();
    int Size();

private:
    void Resize();

private:
    int* m_paData;
    int m_nCapacity;
    int m_nTopIndex;
    int m_nCount;
};

Push操作

进行Push操作时,首先要判断当前栈是否已经满了。如果满了,则调用扩容函数Resize,将数组容量翻倍,以容纳更多元素。然后,将栈顶指针自增,以在新位置添加新的元素。最后,更新栈中元素的数量。具体如何实现,可参考下面的示例代码。

cpp 复制代码
void CArrayStack::Push(int nValue)
{
    if (m_nCount == m_nCapacity)
    {
        Resize();
    }

    m_paData[++m_nTopIndex] = nValue;
    m_nCount++;
}

Pop操作

进行Pop操作时,首先要判断当前栈是否为空。如果为空,则直接抛出异常。然后,将栈顶指针指向的元素返回,同时将栈顶指针自减。最后,更新栈中元素的数量。具体如何实现,可参考下面的示例代码。

cpp 复制代码
int CArrayStack::Pop()
{
    if (IsEmpty())
    {
        throw underflow_error("stack is empty");
    }

    int nValue = m_paData[m_nTopIndex--];
    m_nCount--;
    return nValue;
}

完整实现

Top操作、IsEmpty操作、Size操作都比较简单,这里就不再赘述了。CArrayStack类的完整实现,可参考下面的示例代码。

cpp 复制代码
#include <iostream>
#include <stdexcept>

using namespace std;

CArrayStack::CArrayStack()
{
    m_nCapacity = 2;
    m_paData = new int[m_nCapacity];
    m_nTopIndex = -1;
    m_nCount = 0;
}

CArrayStack::~CArrayStack()
{
    delete[] m_paData;
    m_paData = NULL;
}

void CArrayStack::Push(int nValue)
{
    if (m_nCount == m_nCapacity)
    {
        Resize();
    }

    m_paData[++m_nTopIndex] = nValue;
    m_nCount++;
}

void CArrayStack::Resize()
{
    int nNewCapacity = m_nCapacity * 2;
    int* pNewArray = new int[nNewCapacity];
    for (int i = 0; i < m_nCount; ++i)
    {
        pNewArray[i] = m_paData[i];
    }

    delete[] m_paData;
    m_paData = pNewArray;
    m_nCapacity = nNewCapacity;
}

int CArrayStack::Pop()
{
    if (IsEmpty())
    {
        throw underflow_error("stack is empty");
    }

    int nValue = m_paData[m_nTopIndex--];
    m_nCount--;
    return nValue;
}

int CArrayStack::Top()
{
    if (IsEmpty())
    {
        throw underflow_error("stack is empty");
    }

    return m_paData[m_nTopIndex];
}

bool CArrayStack::IsEmpty()
{
    return m_nCount == 0;
}

int CArrayStack::Size()
{
    return m_nCount;
}


int main()
{
    CArrayStack s;
    s.Push(66);
    s.Push(77);
    s.Push(88);

    cout << "Top element: " << s.Top() << endl;
    cout << "Pop: " << s.Pop() << endl;
    cout << "Pop: " << s.Pop() << endl;
    cout << "Current size: " << s.Size() << endl;
    cout << "Is empty: " << (s.IsEmpty() ? "True" : "False") << endl;
    return 0;
}
相关推荐
见过夏天13 小时前
C++ 基础入门完全指南
c++
CSharp精选营2 天前
关系型 vs 非关系型:从原理到选型,一文搞定数据库核心分类
数据结构·nosql·关系型数据库·非关系型数据库·技术选型
用户805533698032 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
BadBadBad__AK2 天前
线段树维护区间 k 次方和
c++·数学·算法·stl
卷无止境3 天前
Eigen 库如何借助 OpenMP 加速计算
c++·后端
卷无止境3 天前
OpenMPI、MPICH 与 OpenMP:关系、核心概念与架构全解
c++·后端
郝学胜_神的一滴4 天前
CMake 30:循环语法全解|foreach_while双循环精讲、迭代技巧与实战避坑指南
c++·cmake
刘马想放假5 天前
Modbus 全栈技术解析:TCP、RTU、ASCII、RTU over TCP
数据结构·网络协议
北域码匠6 天前
冒泡排序太慢?鸡尾酒排序双向优化,原生 C# 零第三方库完整代码
数据结构·排序算法·泛型·c# 算法·鸡尾酒排序·原生 c# 开发·冒泡排序优化·嵌入式算法
卷无止境6 天前
C++ 的Eigen 库全解析
c++