课程笔记 10:数据结构(清华) 栈

本文探讨了栈作为数据结构在计算机科学中的多种应用,包括进制转换、括号匹配、中缀表达式求值等实例,展示了栈的独特功能和实际应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

栈是一种特殊的线性序列,元素只能从顶端进入,在从顶端弹出,而对栈的底端则不能进行任何操作。因此,栈是一种具有后进先出特点的数据结构。

我们可以基于vector向梁模板类来实现栈。一般来说,栈的接口有:规模size()、判空empty()、入栈push()、出栈pop()、取顶top()。栈的实现如下:

#include <vector>

Template <typename T>

class stack<T> public vector

{

void push (T const &e)

{ insert(size(), e); }

T & pop()

{ return remove(size()); }

T & top()

{ return (*this)[size()]; }

}

有几种实例特别适合使用栈,包括逆序输出、递归调用、延迟缓冲以及部分特殊运算。以下讨论几个栈应用的实例:

1.转化进制。欲将十进制的数转化为n进制的数,通常是通过长除法依次得到从低位到高位的值。在这一过程中就存在着逆序输出的必要。另外,由于事先无法把握转化后输出的长度,因此,使用栈来记录转化的数值是再合适不过的。

Stack<char> & convert (int x, int n)

{

char digit[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

Stack<char> S;

while (x > 0)

{

S.push(digit[x % n]);

x /= n;

}

return & S;

}

如此一来,返回的栈S中就逆序存放着进制转化后的数值。

2.括号匹配。对于一个表达式,要想确认其中所使用的括号是否匹配,可以采用减而治之的思路,将每对邻近括号消去,则剩下的达式括号匹配当且仅当原表达式括号匹配。利用这一思路,我们可以采用栈结构来实现:

bool paren (const char exp[], int n)

{

Stack S;

int j = 0;

for (int i = 0; i < n; i ++)

{

if (exp[i] == '(') S.push(++ j);

if (!S.empty() && (exp[i] == ')'))

S.pop();

if (S.empty() && (exp[i] == ')'))

return false;

}

return S.empty();

}

3.中缀表达式求值。所谓中缀表达式,即二元操作符位于相关操作数之间的的表达式。当我们对它进行运算时,优先考虑的问题是运算的次序。假设一个表达式合法,那么我们首先依照括号来确定各个部分的运算次序,其次才是依照各个运算符的优先级与结合性确定具体的运算次序。具体地说,每一个数的前后都有运算符(不妨设为二元的),那么只有当两个数中间的运算符优先级高于两边时,才会率先进行运算。因此,只要通过一张准确的优先级表,我们就可以在顺序读入中缀表达式的前提下顺利的进行运算了。在这里,我们采用栈结构来实现中缀表达式。

float evaluate(const char exp[])

Stack<float> opnd;

Stack<char> optr;

for (int i = 0; exp[i];)

if (isdigit(exp[i]))

{

opnd.push(exp[i]);

i ++;

}

else

switch(orderbetween(optr.top(), exp[i]))

{

case '<': optr.push(exp[i]); i ++; break;

case '=': optr.pop(); i ++; break;

case '>':

{

char op = optr.pop();

if (op == '!')

opnd.push(calcu(op, opnd.pop()));

else

float op2 = opnd.pop();

float op1 = opnd.pop();

float rs;

rs = calcu(op1, op, op2);

opnd.push(rs);

}

default: return NULL;

}

return (optr.empty()) ? opnd.pop(): NULL;

注:上述算法的实质是通过存放操作数及操作符的两个栈来将原先的中缀表达式转化为后缀表达式加以计算。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值