【011】数据结构:受限线性表之栈的链式存储——C++代码实现(使用模板类)

栈:

  • 是一种特殊的线性表(具有线性关系,即前驱和后继)

特性:

  • 先进后出
  • 限制了线性表插入和删除的位置,始终只在栈顶进行
  • 栈底是固定的,最先进栈的只能在栈底

操作:

  • 栈的插入操作:进栈(压栈)
  • 栈的删除操作:出栈(弹栈)
  • 销毁栈
  • 清空栈
  • 获取栈顶元素
  • 获取栈的大小

栈的链式存储:

  • 栈的链式存储结构,简称链栈,它是运算受限的链表
  • 链栈的存储结构:利用一组地址不连续的存储单元依次存放自栈底到栈顶的数据元素,同时附设指针top指向栈顶元素在链栈中的位置

设计与实现:

  • 栈是一种特殊的线性表,所以栈的链式存储可以通过单链表来实现
  • 栈只是栈顶在做插入和删除操作,所以栈顶应该放在单链表的头部
  • 栈顶在头部,单链表中的头结点就失去了意义,通常对于链栈来说,是不需要头结点的
  • 对于链栈来说,基本不存在栈满的情况,除非内存已经没有使用空间了
  • 若top==NULL,则说明该栈为空

栈的链式存储C++代码实现

LinkStack.hpp

链栈的声明和实现

#ifndef LINKSTACK_H
#define LINKSTACK_H

#include <iostream>
#include "myExceptions.hpp"

template <typename T>
struct chainNode
{
    //数据成员
    T data;
    chainNode<T> *next;

    //方法(初始化链表节点的几种方式)
    chainNode() {}
    chainNode(const T &data)
    {
        this->data = data;
    }
    chainNode(const T &data, chainNode<T> *next)
    {
        this->data = data;
        this->next = next;
    }
};

template <typename T>
class LinkStack
{
private:
    chainNode<T> *stackTop; //栈顶指针
    int stackSize;          //栈中元素个数

public:
    //初始化链栈
    LinkStack()
    {
        stackTop = nullptr;
        stackSize = 0;
    };
    ~LinkStack();
    //判断链栈是否为空
    bool empty()
    {
        return stackSize == 0;
    }
    //返回栈的大小
    int size()
    {
        return stackSize;
    }
    //获取栈顶元素
    T &top()
    {
        if (stackSize == 0)
            throw stackEmpty(); //若栈为空,抛出异常
    
        return stackTop->data;
    }
    //弹出栈顶元素
    void pop();
    //压入元素
    void push(const T &data)
    {
        stackTop = new chainNode<T>(data, stackTop);
        stackSize++;
    }
};

//析构函数
template <typename T>
LinkStack<T>::~LinkStack()
{
    while (stackTop != nullptr) //删除栈顶节点
    {
        chainNode<T> *nextNode = stackTop->next; //缓存栈顶元素的下一个元素
        delete stackTop;                         //释放栈顶元素空间
        stackTop = nextNode;
    }
}

//弹出栈顶元素
template <typename T>
void LinkStack<T>::pop()
{
    if (stackTop == nullptr)
        throw stackEmpty(); //若栈为空,抛出异常

    //删除栈顶节点
    chainNode<T> *nextNode = stackTop->next; //缓存栈顶元素的下一个元素
    delete stackTop;                         //释放栈顶元素空间
    stackTop = nextNode;
    stackSize--;
}

#endif
myExceptions.hpp

自定义异常类型

#ifndef MYEXCEPTIONS_H
#define MYEXCEPTIONS_H

#include <cstring>
#include <iostream>
using namespace std;

//栈为空
class stackEmpty
{
private:
    string message;

public:
    stackEmpty(string theMessage = "Invalid operation on empty stack")
    {message = theMessage;}
    void outputMessage()
    {cout << message << endl;}
};

#endif
main.cpp(测试)
#include <iostream>
#include "LinkStack.hpp"
using namespace std;

struct Person
{
    char name[64];
    int age;
};

int main()
{
    //创建数据
    Person p1, p2, p3, p4, p5;
    strcpy(p1.name, "aaa");
    strcpy(p2.name, "bbb");
    strcpy(p3.name, "ccc");
    strcpy(p4.name, "ddd");
    strcpy(p5.name, "eee");

    p1.age = 10;
    p2.age = 20;
    p3.age = 30;
    p4.age = 40;
    p5.age = 50;

    //创建栈
    LinkStack<Person> stack;
    //入栈
    stack.push(p1);
    stack.push(p2);
    stack.push(p3);
    stack.push(p4);
    stack.push(p5);

    cout << "The stack size is " << stack.size() << endl;

    //输出
    while (stack.empty() != true)
    {
        cout << "The top of the stack is " << stack.top().name << endl;
        stack.pop();
        cout << "Popped top element" << endl;
    }

    //测试异常抛出
    try
    {
        stack.pop();
    }
    catch (stackEmpty message)
    {
        cout << "Last pop failed " << endl;
        message.outputMessage();
    }
    return 0;
}

输出结果
The top of the stack is eee
Popped top element
The top of the stack is ddd
Popped top element
The top of the stack is ccc
Popped top element
The top of the stack is bbb
Popped top element
The top of the stack is aaa
Popped top element
Last pop failed
Invalid operation on empty stack
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值