顺序栈 讲义实现

顺序栈的基本实现及应用

  • 数制转换

在这里插入图片描述

//数制转换(十进制转八进制)
int conversion(int num)
{
	//对于输入的任意一个非负十进制整数,打印输出与其等值的八进制数
	SqStack<int> s;
	int e = 0;
	int result = 0;
	while(num)
	{
		s.Push(num % 8);
		num /= 8;
	}
	while(s.IsEmpty() != EMPTY)
	{
		s.Pop(e);
		result = result*10 + e;
	}
	return result;
}

将取模后的数逐个入栈,再逐个出栈。


  • 表达式求值

中缀表达式求值
创建两个栈,一个保存符号,一个保存数据。

在这里插入图片描述

//判断优先级
char Precede(char o1, char o2)
{
	char f=' ';

	switch(o2)
	{
	case '+':
	case '-':
		if(o1 == '(' || o1 == '#')	//栈中符号优先级低
		{
			f = '<';
		}
		else
		{
			f = '>';
		}
		break;
	case '*':
	case '/':
		if(o1=='*' || o1=='/' || o1==')')
		{
			f = '>';
		}
		else
		{
			f = '<';
		}
		break;
	case '(':
		if(o1 == ')')
		{
			cout<< "括号匹配错误!"<<endl;
			exit(ERROR);
		}
		else
		{
			f = '<';
		}
		break;
	case ')':
		switch(o1)
		{
		case '(':
			f = '=';	//括号匹配
			break;
		case '#':
			cout<< "输入了错误的括号!~"<<endl;
			exit(ERROR);
		default:
			f = '>';	//其他情况站定元素的优先级更大
		}
		break;
	case '#':
		switch(o1)
		{
		case '#':
			f = '=';
			break;
		case '(':
			cout<< "表达式中有多余的括号!!"<<endl;
			exit(ERROR);
		default:
			f = '>';
		}

	}
	return f;
}

//运算函数
int Operate(int a, char theta, int b)
{
	switch(theta)
	{
	case '+':
		return a+b;
		break;
	case '-':
		return a-b;
		break;
	case '*':
		return a*b;
		break;
	case '/':
		return a/b;
		break;
	}
	return 0;
}

int EvalExpr(char *ptr)
{
	SqStack<char> OPTR;	//操作符栈
	OPTR.Push('#');		//表达式起始符为'#'
	SqStack<int> OPND;	//操作数栈
	char op, c, theta=' ', x, m;
	int a=0, b=0;

	c = *ptr++;		//每一个数当做字符取出,ptr遍历后移
	OPTR.GetTop(op);
	while(c != '#' || op != '#')
	{
		if(!In(c))	//如果是数字直接进栈
		{
			m = atoi(&c);	//将字符转化为数字
			OPND.Push(m);	//数字入栈
			c = *ptr++;		//指针后移
		}
		else	//如果是符号的话,则先将这个符号与栈顶符号进行比较
		{
			switch(Precede(op, c))
			{
			case '<':			//栈中符号优先级低,继续进栈
				OPTR.Push(c);
				c = *ptr++;
				break;
			case '=':			//优先级相等时,说明遇到括号,需要托括号
				OPTR.Pop(x);		//脱括号
				c = *ptr++;
				break;
			case '>':			//栈中符号优先级高时,先计算,再将结果压入栈中
				OPTR.Pop(theta);	//运算符
				OPND.Pop(b);		//操作数
				OPND.Pop(a);
				OPND.Push(Operate(a, theta, b));	//将新的运算结果插到栈中
				break;
			}
		}
		OPTR.GetTop(op);	//每一次更新当前栈顶符号
	}

	OPND.GetTop(a);		//计算结果
	return a;
}

后缀表达式求值

在这里插入图片描述

转换后的后缀式中没有括号

转换的过程真的是很核心所在,调试了半天
忽视了可以一次性出多个元素的情况— (+ * -> -)减号进去时 *+都得出来

//将中缀式转化为后缀式
char *change(char *ptr)
{
	char *result = new char;
	int i = 0;
	SqStack<char> OPTR;
	OPTR.Push('#');
	char e=' ', op=' ';
	while(*ptr != '#')
	{
		if(!In(*ptr))
		{
			*(result+i++) = *ptr;
		}
		else
		{
			if(*ptr == '(')	//左括号直接进栈
			{
				OPTR.Push(*ptr);
			}
			else if(*ptr == ')')	//右括号出到左括号为止
			{
				do{
					OPTR.Pop(e);
					if(e != '(')
						*(result+i++) = e;	//将不为左括号的元素进栈
				}while(e != '(');
			}
			else
			{
				OPTR.GetTop(op);
				switch(Precede(op, *ptr))
				{
				case '<':
					OPTR.Push(*ptr);
					break;
				case '=':
				case '>':
					do{
						OPTR.Pop(e);
						*(result+i++) = e;
						OPTR.GetTop(op);
					}while(Precede(op, *ptr) == '>');	//有可能出现多个优先的情况(+*  -)
					//+和*号必须都出去
					OPTR.Push(*ptr);
				}
			}
		}// end of else
		ptr++;
	}// end of while

	while(OPTR.IsEmpty() != EMPTY)
	{
		OPTR.Pop(e);
		if(e != '#')
			*(result+i++) = e;
	}
	*(result+i) = '\0';
	return result;
}

在这里插入图片描述

//后缀表达式求值
int EvalExpr_RPN(char *exp)
{
	SqStack<int> s;
	int a=0, b=0, e=0;
	while(*exp != '\0')		//没有读取到字符串尾部
	{
		if(!In(*exp))	//读取的字符是数字不是符号
		{
			s.Push(*exp-48);	//字符转数字‘1’->1;数字直接入栈
		}
		else
		{
			s.Pop(b);
			s.Pop(a);
			s.Push(Operate(a, *exp, b));	//弹出两个数进行运算
		}
		exp++;		//z指针后移
	}
	s.Pop(e);		//计算结果为e
	return e;
}

  • 递归

在这里插入图片描述
经典例子: Fibonacci数列

int Fib(n)
{
	if(n < 1)
	{
		return 0;
	}
	else if(n <= 2)
	{
		return 1;
	}
	else
	{
		return Fib(n-1)+Fib(n-2);
	}
}

  1. 斐波那契数列的一般实现 --迭代
#include <cstdio>

int main()
{
	int a[20];
	printf("迭代显示斐波那契数列:\n");
	a[0] = 0;
	a[1] = 1;
	printf("%d ", a[0]);
	printf("%d ", a[1]);
	for(int i=2; i<20; i++)
	{
		a[i] = a[i-1] + a[i-2];
		printf("%d ", a[i]);
	}
	printf("\n");
	return 0;
}
  1. 斐波那契数列递归实现

在这里插入图片描述

#include <cstdio>

int Fbi(int i)	//斐波那契递归函数
{
	if(i < 2)
	{
		return i == 0?0:1;
	}
	return Fbi(i-1)+ Fbi(i-2);
}
int main()
{

	printf("递归显示斐波那契数列:\n");
	for(int i=0; i<20; i++)
	{
		printf("%d ", Fbi(i));
	}
	printf("\n");
	return 0;
}

在这里插入图片描述

扫描二维码关注公众号,回复: 3447811 查看本文章

完整源码

#include <iostream>
#include <cstdlib>
using namespace std;

const int STACK_INIT_SIZE = 20;
const int ERROR = 0;
const int OK = 1;
const int EMPTY = 0;

typedef int Status;

template <class T>
class SqStack
{
public:
	SqStack();
	~SqStack();
	Status Push(T e);
	Status Pop(T &e);
	Status GetTop(T &e) const;
	int StackLength() const;
	Status IsEmpty();
	void DispStack();

private:
	T *base;
	T *top;		//栈顶指针
	int stacksize;
};

//初始化一个栈
template <class T>
SqStack<T>::SqStack()
{
	base = new T[STACK_INIT_SIZE];
	top = base;
	stacksize = STACK_INIT_SIZE;
}

//释放一个栈
template <class T>
SqStack<T>::~SqStack()
{
	delete[] base;
}

//取顺序栈栈顶元素算法
template <class T>
Status SqStack<T>::GetTop(T &e) const
{
	if(top == base)
	{
		return ERROR;
	}
	e = *(top-1);
	return OK;
}

//顺序栈入栈
template <class T>
Status SqStack<T>::Push(T e)
{
	if(top - base >= stacksize)
	{
		return ERROR;
	}
	*top++ = e;	//先赋值,再加指针
	return OK;
}

//顺序栈出栈
template <class T>
Status SqStack<T>::Pop(T &e)
{
	if(top == base)
	{
		return ERROR;
	}
	e = *--top;		//先减指针,再取值
	return OK;
}


template <class T>
int SqStack<T>::StackLength() const
{
	int sizeCount =0;
	T *p = top-1;
	while(p >= base)
	{
		sizeCount++;
		p--;
	}
	return sizeCount;
}

template <class T>
Status SqStack<T>::IsEmpty()	//空栈为0,非空栈为1;
{
	if(top == base)
	{
		return EMPTY;
	}
	else
	{
		return OK;
	}
}

template <class T>
void SqStack<T>::DispStack()
{
	T *p = top-1;
	while(p >= base)
	{
		cout<< *p << " ";
		p--;
	}
	cout<< endl;
}

bool In(char c)
{
	if(c>48 && c<57)
	{
		return false;
	}
	else
	{
		return true;
	}
}

//数制转换(十进制转八进制)
int conversion(int num)
{
	//碎玉输入的任意一个非负十进制整数,打印输出与其等值的八进制数
	SqStack<int> s;
	int e = 0;
	int result = 0;
	while(num)
	{
		s.Push(num % 8);
		num /= 8;
	}
	while(s.IsEmpty() != EMPTY)
	{
		s.Pop(e);
		result = result*10 + e;
	}
	return result;
}

//判断优先级
char Precede(char o1, char o2)
{
	char f=' ';

	switch(o2)
	{
	case '+':
	case '-':
		if(o1 == '(' || o1 == '#')	//栈中符号优先级低
		{
			f = '<';
		}
		else
		{
			f = '>';
		}
		break;
	case '*':
	case '/':
		if(o1=='*' || o1=='/' || o1==')')
		{
			f = '>';
		}
		else
		{
			f = '<';
		}
		break;
	case '(':
		if(o1 == ')')
		{
			cout<< "括号匹配错误!"<<endl;
			exit(ERROR);
		}
		else
		{
			f = '<';
		}
		break;
	case ')':
		switch(o1)
		{
		case '(':
			f = '=';	//括号匹配
			break;
		case '#':
			cout<< "输入了错误的括号!~"<<endl;
			exit(ERROR);
		default:
			f = '>';	//其他情况站定元素的优先级更大
		}
		break;
	case '#':
		switch(o1)
		{
		case '#':
			f = '=';
			break;
		case '(':
			cout<< "表达式中有多余的括号!!"<<endl;
			exit(ERROR);
		default:
			f = '>';
		}

	}
	return f;
}

//运算函数
int Operate(int a, char theta, int b)
{
	switch(theta)
	{
	case '+':
		return a+b;
		break;
	case '-':
		return a-b;
		break;
	case '*':
		return a*b;
		break;
	case '/':
		return a/b;
		break;
	}
	return 0;
}

int EvalExpr(char *ptr)
{
	SqStack<char> OPTR;	//操作符栈
	OPTR.Push('#');		//表达式起始符为'#'
	SqStack<int> OPND;	//操作数栈
	char op, c, theta=' ', x, m;
	int a=0;	//操作数a
	int b=0;	//操作数b

	c = *ptr++;		//每一个数当做字符取出,ptr遍历后移
	OPTR.GetTop(op);
	while(c != '#' || op != '#')
	{
		if(!In(c))	//如果是数字直接进栈
		{
			m = atoi(&c);	//将字符转化为数字
			OPND.Push(m);	//数字入栈
			c = *ptr++;		//指针后移
		}
		else	//如果是符号的话,则先将这个符号与栈顶符号进行比较
		{
			switch(Precede(op, c))
			{
			case '<':			//栈中符号优先级低,继续进栈
				OPTR.Push(c);
				c = *ptr++;
				break;
			case '=':			//优先级相等时,说明遇到括号,需要托括号
				OPTR.Pop(x);		//脱括号
				c = *ptr++;
				break;
			case '>':			//栈中符号优先级高时,先计算,再将结果压入栈中
				OPTR.Pop(theta);	//运算符
				OPND.Pop(b);		//操作数
				OPND.Pop(a);
				OPND.Push(Operate(a, theta, b));	//将新的运算结果插到栈中
				break;
			}
		}
		OPTR.GetTop(op);	//每一次更新当前栈顶符号
	}

	OPND.GetTop(a);		//计算结果
	return a;
}

//将中缀式转化为后缀式
char *change(char *ptr)
{
	char *result = new char;
	int i = 0;
	SqStack<char> OPTR;
	OPTR.Push('#');
	char e=' ', op=' ';
	while(*ptr != '#')
	{
		if(!In(*ptr))
		{
			*(result+i++) = *ptr;
		}
		else
		{
			if(*ptr == '(')	//左括号直接进栈
			{
				OPTR.Push(*ptr);
			}
			else if(*ptr == ')')	//右括号出到左括号为止
			{
				do{
					OPTR.Pop(e);
					if(e != '(')
						*(result+i++) = e;	//将不为左括号的元素进栈
				}while(e != '(');
			}
			else
			{
				OPTR.GetTop(op);
				switch(Precede(op, *ptr))
				{
				case '<':
					OPTR.Push(*ptr);
					break;
				case '=':
				case '>':
					do{
						OPTR.Pop(e);
						*(result+i++) = e;
						OPTR.GetTop(op);
					}while(Precede(op, *ptr) == '>');	//有可能出现多个优先的情况(+*  -)
					//+和*号必须都出去
					OPTR.Push(*ptr);
				}
			}
		}// end of else
		ptr++;
	}// end of while

	while(OPTR.IsEmpty() != EMPTY)
	{
		OPTR.Pop(e);
		if(e != '#')
			*(result+i++) = e;
	}
	*(result+i) = '\0';
	return result;
}


//后缀表达式求值
int EvalExpr_RPN(char *exp)
{
	SqStack<int> s;
	int a=0, b=0, e=0;
	while(*exp != '\0')		//没有读取到字符串尾部
	{
		if(!In(*exp))	//读取的字符是数字不是符号
		{
			s.Push(*exp-48);	//字符转数字‘1’->1;数字直接入栈
		}
		else
		{
			s.Pop(b);
			s.Pop(a);
			s.Push(Operate(a, *exp, b));	//弹出两个数进行运算
		}
		exp++;		//z指针后移
	}
	s.Pop(e);		//计算结果为e
	return e;
}

int main()
{
	SqStack<int> stack1;
	for(int i=0; i<10; i++)
	{
		stack1.Push(i);
	}
	stack1.DispStack();
	cout<< stack1.StackLength()<< endl;
	int temp = 0;
	stack1.GetTop(temp);
	cout<< "temp = " << temp<< endl;

	cout << stack1.IsEmpty() << endl;
	stack1.Push(10);
	stack1.DispStack();
	cout <<stack1.Pop(temp)<< endl;
	cout<< temp<<endl;
	stack1.DispStack();

	cout << "****************" << endl;
	cout << "请输入一个整数:";
	int num = 0;
	cin >> num;
	cout << num << "对应的八进制数为:" << conversion(num) <<endl;

	char a[17] = "1+2*(5-3)-6/2+4#";
	char *exp = a;
	int opnd = EvalExpr(exp);
	cout<< "作为示例 " << exp << "的计算结果为 " << opnd <<endl;

	cout << exp << "转化为后缀表达式为"  << change(exp) <<endl;
	cout << "后缀表达式求值为" << EvalExpr_RPN(change(exp)) <<endl;

	return 0;
}

运行结果
结果

猜你喜欢

转载自blog.csdn.net/HdUIprince/article/details/82945699