栈&栈的应用

关于数据结构栈的相关应用,有以下几个任务需要我们完成。

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;
}
运行结果:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值