阅读建议:
一、实验目的
二、实验内容
三、实验过程
四、代码结构
五、测试结果
阅读建议:
1.实验的软硬件环境要求:
(1)硬件环境要求:PC机
(2)软件环境要求:Windows 环境下的 Microsoft Visual Studio2.该实验采用了头文件(.h)和源文件(.cpp)相结合的形式。
1.熟练掌握栈的链式存储结构的实现;
2.熟练掌握链栈的基本操作算法实现,包括建栈、入栈、出栈、读栈顶元素和释放栈等;
3.灵活使用栈来解决具体的问题。
1.定义链栈类,封装链栈的基本操作算法;(建议将链栈的类模板及实现算法单独写入.h头文件中);
2.利用链栈的基本操作与特性,从以下题目中选择一个完成:
(1)十进制数转换为二、八、十六进制数
(2)算术表达式的括号匹配合法性判断(表达式中包括的括号类型有圆括号()、方括号[]以及花括号{})
(3)简单算术表达式求值。(表达式里包含运算数、+、-、*、/四类运算符及小括号())
1.结点结构
template
struct Node
{
T data; //数据域
Node* next; //指针域
};
2.构造函数,初始化一个空的链栈。
工作原理:在链栈中,
top
通常表示栈顶元素,而这里将其初始化为NULL
,意味着一开始这个链栈是空的,没有栈顶元素。
template
LinkStack::LinkStack()
{
top = NULL; //初始化栈顶指针为空
}
3.析构函数,删除LinkStack
对象时,自动清理其占用的内存资源。
工作原理:代码遍历了链栈中的所有节点,并释放了它们所占用的内存。这是通过一个循环实现的,循环条件是
top != NULL
,即只要栈顶指针不为空,就继续循环。在循环中,首先将当前栈顶指针赋值给p
,然后将top
指向下一个节点,接着删除p
指向的节点。这样,所有的节点都会被遍历并释放,从而确保链栈所占用的内存被正确地释放。
template
LinkStack::~LinkStack()
{
Node* p = NULL;
while (top != NULL) {
p = top;
top = top->next;
delete p;
}
}
4.入栈操作,将一个元素压入链栈的栈顶。
工作原理:首先创建一个新的节点指针
p
并初始化为NULL
。然后通过new
操作符动态分配内存,并将新节点的指针赋值给p
。接着,将元素x
赋值给新节点的数据域,并将新节点的next
指针指向当前的栈顶元素(即top
)。最后,更新栈顶指针top
,使其指向新节点,完成压栈操作。
template
void LinkStack::Push(T x)
{
Node* p = NULL;
p = new Node;
p->data = x;
p->next = top;
top = p; //将p插在栈顶
}
5.出栈操作,从链栈的栈顶弹出元素,并返回其值。
工作原理:首先创建一个新的节点指针
p
并初始化为NULL
,以及一个变量x
用于存储弹出元素的值。然后,通过一个if
语句检查栈是否为空。如果栈为空(即栈顶指针top
为NULL
),则抛出一个异常,表示下溢。如果栈不为空,则将栈顶节点的数据域赋值给变量
x
,并将栈顶指针top
暂存到指针变量p
中。接着,将栈顶指针top
更新为下一个节点,即将栈顶节点从链表中摘除。最后,释放暂存的栈顶节点的内存,并返回弹出元素的值。
template
T LinkStack::Pop()
{
Node* p = NULL;
T x;
if (top == NULL) {
throw "下溢";
}
x = top->data;
p = top; //暂存栈顶元素
top = top->next; //将栈顶节点摘除
delete p;
return x;
}
6.读栈顶元素,获取链栈的栈顶元素的值,如果链栈为空则返回-1。
工作原理:首先通过一个
if
语句检查链栈是否为空。如果链栈为空(即栈顶指针top
为NULL
),则输出一个错误信息并返回-1。如果链栈不为空,则直接返回栈顶节点的数据域的值。
template
T LinkStack::GetTop()
{
if (Empty()) {
cout << "栈链为空!" << endl;
return -1;
}
return top->data;
}
7.判断链栈是否为空。
工作原理:函数返回一个布尔值,如果链栈的栈顶指针
top
为NULL
,即链栈为空,则返回true
;否则返回false
。
template
bool LinkStack::Empty()
{
return top == NULL;
}
8.检查括号是否匹配。
工作原理:函数接受两个字符参数
l
和r
,分别表示左括号和右括号。函数通过一个if
语句判断左括号和右括号是否匹配,如果匹配则返回true
,否则返回false
。
template
bool LinkStack::isPaired(char l, char r)
{
if ((l == '(' && r == ')') || (l == '[' && r == ']') || (l == '{' && r == '}'))
return true;
else
return false;
}
9.检查表达式的括号是否匹配。
工作原理:函数接受一个字符串参数
expr
,表示待判断的表达式。函数首先创建一个空的链栈s
,然后遍历表达式中的每个字符。对于每个左括号(即(
、[
或{
),将其压入栈中;对于每个右括号(即)
、]
或}
),首先检查栈是否为空。如果栈为空,则表达式不合法,返回false
。如果栈不为空,但当前右括号与栈顶的左括号不匹配,则表达式不合法,返回false
。在遍历完表达式中的所有括号后,继续检查栈中是否还有剩余的左括号。如果有,则将栈中的每个左括号与一个虚拟的右括号(用
NULL
表示)进行匹配检查。如果某个左括号与虚拟的右括号不匹配,则表达式不合法,返回false;
如果表达式中的所有括号都匹配合法,则返回true
。
template
bool LinkStack::ParenthesesMatch(string expr)
{
LinkStack s;
for (char c : expr) {
if (c == '(' || c == '[' || c == '{') {
s.Push(c);
}
else if (c == ')' || c == ']' || c == '}') {
if (s.Empty()==true) {
return false;
}
else if (isPaired(s.Pop(), c)==false) {
return false;
}
}
}
while (!s.Empty()) {
if (isPaired(s.Pop(), NULL) == false) {
return false;
}
}
return true;
}
1.基本操作
2.算术表达式的括号匹配合法性判断
完整代码链接:https://download.csdn.net/download/weixin_73286497/88758690
希望大家可以在该篇实验报告中有所收获,同时也感谢各位大佬的支持。文章如有任何问题请在评论区留言斧正,鸿蒙会尽快回复您的建议!