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

概述

在前一篇文章中,我们已经用数组实现了栈。在本篇文章中,我们将使用链表来实现栈。使用链表的优点是:动态增长,扩容时更加平滑。缺点是:略微复杂,需要额外管理所有节点。栈相关的操作,仍然是下面5个接口。

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

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

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

IsEmpty:检查栈是否为空。

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

实现原理

我们使用一个带头指针的单链表来实现栈。其中,栈顶对应链表的头部,栈底对应链表的尾部。有一个指针始终指向当前栈顶节点,即链表的第一个节点,每次插入/删除都在链表头部进行。这样做的好处是:所有栈操作只需要修改头指针即可,效率非常高。

在下面栈CLinkedListStack的实现中,我们声明了一个成员变量m_pTop。m_pTop代表栈顶,指向单链表的第一个节点。

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

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

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

private:
    // 定义链表节点结构
    struct Node
    {
        int nData;
        struct Node* pNext;
    };

    Node* m_pTop;
};

Push操作

入栈就是在链表的头部插入一个新节点,详细步骤如下。

1、创建一个新节点。

2、新节点的pNext指向当前栈顶。

3、更新栈顶为新节点。

具体如何实现,可参考下面的示例代码。

cpp 复制代码
void CLinkedListStack::Push(int nValue)
{
    Node* pNode = new Node();
    pNode->nData = nValue;
    pNode->pNext = m_pTop;
    m_pTop = pNode;
}

Pop操作

出栈就是删除链表头部节点,并返回其值,详细步骤如下。

1、如果栈为空,抛出异常。

2、取出栈顶节点的值,保存为临时变量。

3、将栈顶指针下移一位。

4、释放旧节点的内存。

5、返回上面的临时变量。

具体如何实现,可参考下面的示例代码。

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

    Node* pTemp = m_pTop;
    int nValue = pTemp->nData;
    m_pTop = m_pTop->pNext;
    delete pTemp;
    return nValue;
}

完整实现

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

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

using namespace std;

CLinkedListStack::CLinkedListStack() : m_pTop(NULL)
{
    NULL;
}

CLinkedListStack::~CLinkedListStack()
{
    while (!IsEmpty())
    {
        Pop();
    }
}

void CLinkedListStack::Push(int nValue)
{
    Node* pNode = new Node();
    pNode->nData = nValue;
    pNode->pNext = m_pTop;
    m_pTop = pNode;
}

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

    Node* pTemp = m_pTop;
    int nValue = pTemp->nData;
    m_pTop = m_pTop->pNext;
    delete pTemp;
    return nValue;
}

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

    return m_pTop->nData;
}

bool CLinkedListStack::IsEmpty()
{
    return m_pTop == NULL;
}

int CLinkedListStack::Size()
{
    int nSize = 0;
    Node* pTemp = m_pTop;
    while (pTemp != NULL)
    {
        ++nSize;
        pTemp = pTemp->pNext;
    }

    return nSize;
}

int main()
{
    CLinkedListStack 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;
}
相关推荐
坤坤子吖7 小时前
Linux网络编程:TCP服务器的多进程与多线程实现
linux·服务器·开发语言·网络·c++·笔记·学习
一晌小贪欢8 小时前
Python基础:第 09 篇 · while 循环:重复直到不满足
开发语言·c++·python·数据可视化·面向对象·python办公
zh_xuan8 小时前
LeeCode 496. 下一个更大元素I
数据结构·算法·栈·单调栈
xiaoye-duck8 小时前
《C++ 项目:手写大模型接入 SDK》LLMManager架构设计与实现
开发语言·网络·c++·语言模型
一条大祥脚9 小时前
CuTe 与 CuTe DSL:从 C++ 模板元编程到 Python DSL 的 GPU 编程演进
开发语言·c++·python·cutlass·cute·cute dsl
·present·9 小时前
CSAPP(lecture 13_02 Linking)
c语言·c++
旖旎夜光10 小时前
【C++ 基础入门】C++ 多态(上):虚函数、重写、override/final 与抽象类
开发语言·c++·笔记·学习
青少儿编程课堂11 小时前
蓝桥杯青少组图形化 STEMA 省考(报名倒计时·11/22开考)+ 全国青少年信息素养大赛 2026—2027赛季 + 电子学会图形化考级:校园华容道大闯关
c++·python·算法·bfs·信息学竞赛
白杨尚青12 小时前
C++进阶篇(五):红黑树——四条规则、三种插入情况与旋转变色
开发语言·数据结构·c++·stl·红黑树·平衡二叉树
旖旎夜光13 小时前
【C++ 基础入门】C++ 继承(上):概念、切片、隐藏、默认成员函数与友元
c++·笔记·学习