关于数据结构栈的相关应用,有以下几个任务需要我们完成。
1.动态顺序栈的实现
#include<iostream>
using namespace std;
template <class T>
class Stack
{
public:
Stack()
{
_capacity = 0;
_size = 0;
_array = NULL;
}
~Stack()
{
if (_array != NULL)
{
delete[] _array;
_array = NULL;
}
}
void Push(const T& data)
{
CheckCapacity();//一定要有内存空间才可以压栈
_array[_size] = data;
_size++;
}
void Pop()
{
if ((_array != NULL) && (_size != 0))
{
_size--;
}
}
T& Top()
{
if ((_array != NULL) && (_size != 0))
{
return _array[_size - 1];
}
else
{
int t = -1;
return t;
}
}
T& Top()const//对top函数内的成员变量不能修改
{
if ((_array != NULL) && (_size != 0))
{
return _array[_size - 1];
}
else
{
int t = -1;
return t;
}
}
size_t Size()const
{
return _size;
}
bool Empty()const//判空
{
if ((_array != NULL) && (_size != 0))
{
return false;
}
else
return true;
}
private:
void CheckCapacity()//检查并扩容
{
if (_capacity == _size)
{
if (_array == NULL)
{
_array = new T[2 * _capacity + 1];
}
else
{
T* temp = new T[2 * _capacity + 1];
int pos = 0;
while (pos < _size)
{
temp[pos] = _array[pos];
pos++;
}
delete[] _array;
_array = temp;
}
_capacity = 2 * _capacity + 1;
}
}
T* _array;//栈用数组实现,定义数组,
size_t _capacity;//定义容量
size_t _size;//size_t相当于unsigned int,定义大小
};
int main()
{
Stack<int>S;
cout << S.Size() << endl;
S.Push(1);
S.Push(2);
S.Push(3);
S.Push(4);
cout << S.Size() << endl;
cout << S.Top() << endl;
cout << S.Size() << endl;
cout << S.Empty() << endl;
S.Pop();
S.Pop();
S.Pop();
S.Pop();
S.Pop();
cout << S.Size() << endl;
cout << S.Top() << endl;
cout << S.Empty() << endl;
return 0;
}
程序运行结果:
2.栈之应用--括号匹配
做题思想:括号匹配主要有两种情况
左括号多于右括号、右括号多于左括号、次序匹配不成功、匹配成功
(1)当字符串为空时,直接返回true;
(2)当字符串不为空时,开始遍历字符串。遇到非“(”、“)”、“[”、“]”、“{”、“}”这些括号时,让字符串继续往后遍历,直到遇到括号(或字符串遍历结 束)。定义一个栈,将左括号压栈,遇到右括号时,令栈顶的左括号与该右括号进行匹配。
当栈为空时,说明右括号多于左括号;
当字符串遍历结束后,栈不为空,说明左括号多于右括号;
当右括号与栈顶的左括号不匹配时,说明次序不匹配
当每次遍历的右括号都和栈顶的左括号匹配,并且栈内为空,字符串遍历结束,说明括号匹配成功。
程序代码:
#include<iostream>
using namespace std;
#include<stack>
bool MatchBrackets(char* pStr)
{
if (pStr == NULL)
{
return true;
}
else
{
stack<char> s;
char* str = pStr;
while (*str != '\0')//遍历--判断str是否为空,如果不为空就可以进行括号匹配的问题检测
{
if ((*str == '(') || (*str == ')') || (*str == '[') || (*str == ']')\
|| (*str == '{') || (*str == '}'))//如果在遍历过程中遇到这几种情况,则说明是括号,可以进行下面的判断
{
if ((*str == '(') || (*str == '[') || (*str == '{'))//左括号,压栈
{
s.push(*str);
str++;
}
else//右括号与左括号匹配
{
if (s.empty())
{
return false;//左括号少于右括号
}
else
{
if ((s.top() == '(' && (*str == ')')) || (s.top() == '[' \
&& (*str == ']')) || (s.top() == '{' && (*str == '}')))
{
s.pop();
str++;
}
else//次序匹配不成功
return false;
}
}
}
else//当不是括号时
str++;
}
if (!s.empty())//左多于右
{
return false;
}
else
return true;
}
}
int main()
{
char array[] = "((asg{[l]";// 0
cout << MatchBrackets(array) << endl;
char array1[] = "((asg{[l]}))";// 1
cout << MatchBrackets(array1) << endl;
char array2[] = "asg{[l]]]]";// 0
cout << MatchBrackets(array2) << endl;
char array3[] = "((asg{[l]]))";// 0
cout << MatchBrackets(array3) << endl;
return 0;
}
运行结果:
3.栈之应用--计算后缀表达式
(1)在计算后缀表达式时,我们需要将平时常用的中缀表达式转换成后缀表达式。(在这里给大家介绍一下前中后缀表达式的区别)
上面是一个简单的后缀解释,后缀表达式中还有一些比较复杂的情况。如下图
下面,我们用代码实现以下这个过程
#include<iostream>
#include<string>
#include<stack>
#include<vector>
using namespace std;
int Find(char c)
{
if (c == '*' || c == '/')
return 2; // *、/ 优先级给2
else if (c == '+' || c == '-')
return 1; //+、- 优先级给1
else
return 0; // (、)、数字返回0
}
string InFix2PostFix(string s1, int size)
{
string s; //后缀字符串
if (s1.size() == 0)
return s; //返回空的后缀字符串
else
{
stack<char> str;
for (int i = 0; i < size; i++)
{
if (Find(s1[i]) == 0 && s1[i] != '('&& s1[i] != ')') //字符为数字,直接插入到后缀字符串中
{
s.push_back(s1[i]);
}
else
{ //字符不是数字
if (str.empty())
str.push(s1[i]); //字符栈为空,直接压栈
else
{
if (s1[i] == '(') //字符为左括号,直接压栈
str.push(s1[i]);
else if (s1[i] == ')') // 字符为右括号,将栈中左括号之后的字符全部插入到后缀字符串中并出栈
{
while (str.top() != '(')
{
s.push_back(str.top());
str.pop();
}
str.pop(); //删除左括号
}
else
{ //字符为运算符
while (!str.empty() && Find(s1[i]) <= Find(str.top()) && str.top() != '(') //与字符栈顶运算符优先级进行对比
//比该遍历字符优先级高或者相同的栈顶元素插入到后缀字符串中,同时出栈
{
s.push_back(str.top());
str.pop();
}
str.push(s1[i]); //将遍历字符压入字符栈中
}
}
}
}
while (!str.empty()) //保证字符栈为空,不为空时,将字符弹出并插入到后缀字符串中
{
s.push_back(str.top());
str.pop();
}
return s; //返回后缀字符串
}
}
int main()
{
string s;
cout << "请输入正确的中缀表达式:";
cin >> s;
string s1 = InFix2PostFix(s, s.size());
cout << "后缀表达式为:" << s1 << endl;
return 0;
}
运行结果:
(2)将中缀表达式转换为后缀表达式以后,我们就来计算后缀表达式
下面是后缀表达式的一个计算过程
接下来用代码实现以下这个过程
#include<iostream>
using namespace std;
#include<stack>
int CalcRPN(string str,int size)
{
stack<int>s;
if (str.empty())
return 0;
else
{
for (int i = 0; i < size; i++)
{
if (str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/')
{
int num1 = s.top();
s.pop();
int num2 = s.top();
s.pop();
switch (str[i])
{
case '+':
s.push(num2 + num1);
break;
case '-':
s.push(num2 - num1);
break;
case '*':
s.push(num2*num1);
break;
case '/':
s.push(num2 / num1);
break;
}
}
else
{
s.push(str[i]);
}
}
}
return s.top();
}
int main()
{
string str;
str.push_back(12);
str.push_back(3);
str.push_back(4);
str.push_back('+');
str.push_back('*');
str.push_back(6);
str.push_back('-');
str.push_back(8);
str.push_back(2);
str.push_back('/');
str.push_back('+');
cout << CalcRPN(str, str.size()) << " " << endl;
return 0;
}
运行结果: