栈:
- 是一种特殊的线性表(具有线性关系,即前驱和后继)
特性:
- 先进后出
- 限制了线性表插入和删除的位置,始终只在栈顶进行
- 栈底是固定的,最先进栈的只能在栈底
操作:
- 栈的插入操作:进栈(压栈)
- 栈的删除操作:出栈(弹栈)
- 销毁栈
- 清空栈
- 获取栈顶元素
- 获取栈的大小
栈的链式存储:
- 栈的链式存储结构,简称链栈,它是运算受限的链表
- 链栈的存储结构:利用一组地址不连续的存储单元依次存放自栈底到栈顶的数据元素,同时附设指针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