用栈实现的简单操作

众所周知,栈(stack)是限定在表尾进行插入或删除操作的线性表,其特点是后进先出
允许删除和插入的一端称为栈顶(top),另一端称为栈底(base)
根据这个特性,可以实现多种实际应用,本文跟大家分享十进制转换其他进制数括号匹配检验的应用举例

栈的实现和表示

头文件、常量定义和栈的定义

#include<iostream>
using namespace std;
#define OK 1
#define ERROR 0
#define STACK_INIT_SIZE 100   //设置存储空间初始分配量为100
#define STACKINCREMENT  10    //设置存储空间分配增量为10
typedef int Status;
#define SElemType int

typedef struct {                    
	SElemType* base;
	SElemType* top;
	int stacksize;
}SqStack;                   //栈的定义

创建空栈

Status InitStack(SqStack& S)      //创建空栈
{
	S.base = (SElemType*)malloc(STACK_INIT_SIZE * sizeof(SElemType));
	if (!S.base) exit(1);         //存储分配失败
	S.top = S.base;
	S.stacksize = STACK_INIT_SIZE;
	return OK;
}

判断栈是否为空,是否已满

int StackEmpty(SqStack S)        //判断栈是否为空
{
	if (S.top == S.base) return 1;    //为空
	else return 0;
}


int StackFull(SqStack S)          //判断栈是否满
{
	if (S.top - S.base >= S.stacksize) return 1;       //已满
	else return 0;
}

入栈(即插入元素)

Status  Push(SqStack& S, SElemType e)       //入栈
{
	if (S.top - S.base >= S.stacksize)   //若栈满,增加存储空间
	{
		S.base = (SElemType*)realloc(S.base, (S.stacksize + STACKINCREMENT) * sizeof(SElemType));
		if (!S.base) exit(1);
		S.top = S.base + S.stacksize;
		S.stacksize += STACKINCREMENT;
	}
	*S.top++ = e;              //等价于 *S.top=e; S.top++;
	return  OK;
}

出栈(即删除元素)

Status Pop(SqStack& S,SElemType &e)                    //出栈,并用e返回删除值
{
	if (S.top == S.base) return ERROR;     //若为空栈,出错
	e=*--S.top;              //相当于e=*(S.top-1); --S.top;   
	return OK;
}

返回栈顶元素

Status GetTop(SqStack S, SElemType& e)    //返回栈顶元素
{
	if (S.base == S.top) return ERROR;    //若为空栈,出错
	e = *(S.top-1);
	return 0;
}

此处说明,S.top指针是指向最上面一个元素上面的一个空间,是没有数据值的,如图:
在这里插入图片描述
对比入栈出栈和取栈顶元素
入栈时,对S.top先赋值,后自加

	*S.top++ = e;              //等价于 *S.top=e; S.top++;

取栈顶元素,即取(S.top-1)的值

	e = *(S.top-1);

出栈时,先取栈顶元素,再自减

	e=*--S.top;              //相当于e=*(S.top-1); --S.top; 

数制转换的思路(举例十进制转八进制)

在这里插入图片描述
由于十进制转其他进制数的方法中,计算顺序和输出顺序相反,故可以利用栈的“后进先出”的特点,来实现十进制向其他进制的转换。
思路如下:

  1. 初始化一个栈,输入一个十进制数
  2. 将十进制数除以8,把余数入栈
  3. 将商作为被除数,重复第一步,直到商为0
  4. 当商为0时,输出栈
void convert()           //将十进制数转换为八进制数
{
	int p,e;
	SqStack S;
	InitStack(S);
	cin >> p;
	while (p)
	{
		Push(S, p % 8);
		p = p / 8;
	}
	while (!StackEmpty(S))
	{
		Pop(S, e);
		cout << e;
	}
	cout << endl;
}

括号匹配检验

本函数只识别两种括号:"("、")"、"["、"]"
其他括号思路相同,以此类推
思路如下:

  1. 初始化一个栈,输入一个括号序列
  2. 依次对括号序列中的字符进行如下判断:
    2.1 如果是左括号,则进栈,回到步骤2
    2.2 如果是其他字符,则格式不正确。程序结束
    2.3 如果是右括号,则取出栈顶元素判断:
  • 2.3.1 若右括号与栈顶元素匹配,回到步骤2

  • 2.3.2 若右括号与栈顶元素不匹配,则格式不正确。程序结束

3.判断栈是否为空栈,若为空,则括号序列格式正确,否则,格式错误

void match()
{
	SqStack S;
	InitStack(S);
	char a[20];
	int i = 0;
	cin >> a;
	while (a[i] != '\0')
	{
		if (a[i] == '(' || a[i] == '[')
		{
			Push(S, a[i]);
			i++;
		}
	else if (a[i] == ')' || a[i] == ']')
		{
			SElemType e;
			if (!StackEmpty(S))
			{
				Pop(S, e);
				if ((a[i] == ')' && e == '(') || (a[i] == ']' && e == '['))    i++;
				else { cout << "不匹配" << endl; return; }
			}
			else { cout << "不匹配" << endl; return; }
		}
	else { cout << "不匹配,请输入正确的括号" << endl; return; }
		}
	if (StackEmpty(S))  cout << "匹配" << endl;
	else cout << "不匹配" << endl;
}

主函数

int main()
{
	char a;
	cout << " 1.十进制数转八进制数    2.括号匹配检验  0.退出" << endl;
	while (1)
	{
		cout << "请输入想要执行的操作:";
			cin >> a;
		switch (a)
		{
		case '1': cout << "请输入十进制数:";  convert(); break;
		case '2': cout << "请输入一组括号(英文括号“( ) [ ]”):"; match(); break;
		case '0': exit(0); break;
		default:cout << "请重新输入正确操作!" << endl; break;
		}
	}
	return 0;
}

运行如下
在这里插入图片描述

对于主函数中的switch语句,我存在以下未解决的问题:

  • 当a定义为字符型数据时,若误输多个字节的数据,则不会执行default,而是一个一个识别字符。
    如图在这里插入图片描述

  • 当a定义为整型时,可输入多位数整型数据,但是输入字符数据时会直接跳出程序
    如图在这里插入图片描述

  • 当a定义为字符串数组时,string类型使用于switch语句上转换定义相关较为复杂,还没有足够丰富的知识来解决

  • 有人说我多虑了,不会出现这些情况,因为交互性中已经说明清楚了操作对应的数据,但是这些情况是实际存在的,还未解决,只怨学识不够,会继续学习!

我低头帮陌生人拾起掉落的书的时候,心里已经划过了整个四季

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值