数据结构-顺序栈详解(超基础的那种)

顺序栈的设计及运行

1. 顺序栈

栈是在顺序表和链表的基础上学习的另一种存储形式,是只能在表的一端(栈顶)进行插入和删除的线性表,也就是遵循先进后出的原则,它与线性表一样,仍然是一对一的关系,根据存储关系不同,可以分为顺序栈和链栈,这里我来演示一下顺序栈的C语言操作。
在这里插入图片描述

还是那句话,没有什么是操作一遍解决不了的,如果还有的话,那就再来一遍,嗯,请叫这句话为lanyan理论,哈哈嗝。

2. 代码部分

  1. 主函数(主函数没啥看的,理解一下我是怎么调用各种函数的操作就行)
#include"basic.h"

int main()
{
	int choose = -1;
	SElemType e;		//定义一个结构体的元素e
	SqStack S;		//定义一个顺序栈的变量S
	InitStack(S);		//初始化顺序栈
	cout << "本次服务共有以下内容:" << endl << endl;
	cout << "1. 顺序栈的初始化" << endl;
	cout << "2. 判断栈是否为空" << endl;
	cout << "3. 判断顺序栈的长度" << endl;
	cout << "4. 清空顺序栈" << endl;
	cout << "5. 销毁顺序栈" << endl;
	cout << "6. 顺序栈入栈" << endl;
	cout << "7. 顺序栈出栈" << endl;
	cout << "8. 取顺序栈顶元素" << endl;
	cout << "0. 退出" << endl << endl;
	
	while (choose != 0) {

		cout << "请选择您需要的服务:" << endl;		//输入选择
		do {
			cin >> choose;
			if (choose < 0 || choose>8)
				cout << "您输入的信息不在本次服务之内,请重新输入:" << endl;
		} while (choose < 0 || choose>8);
		switch (choose)

		{
		case 1:
			if (InitStack(S))  cout << "顺序栈初始化成功!" << endl << endl;
			else cout << "顺序栈初始化失败!" << endl << endl;;
			break;
		case 2:
			if (StackEmpty(S))	cout << "此顺序栈为空!" << endl << endl;
			else cout << "此顺序栈不为空!" << endl << endl;
			break;
		case 3:
			cout << "此时栈内共有" << StaticLength(S) << "个元素" << endl<<endl;
			break;
		case 4:
			if (ClearStack(S)) cout << "清空顺序表成功" << endl << endl;
			break;
		case 5:
			if (DestroyStack(S)) cout << "销毁顺序表成功" << endl << endl;
			break;
		case 6:
			cout << "请依次输入姓名和学号" << endl;
			cin >> e.name>> e.mumber;
			if (Push(S, e))	cout << "该元素入栈成功" << endl << endl;
			break;
		case 7:
			Pop(S, e);
			cout << "您本次取出的元素为:" << endl;
			cout << e.name << "  " << e.mumber << endl<<endl;
			break;
		case 8:
			GetTop(S, e);
			cout << "您此时栈顶的元素为:" << endl;
			cout << e.name << "  " << e.mumber << endl << endl;
			break;
		default:break;
		}
	}
	return 0;
}
  1. basic.h头文件(嗯,关键信息都在这里,敲黑板划重点了)
#pragma once
#include<iostream>
using namespace std;
#define OVERFLOW -2
#define OK 1
#define ERROR 0
#define MAXSIZE 100

typedef int Status;

typedef struct		//定义一个的结构体
{
	char name[30];		//姓名
	char mumber[30];		//学号
}SElemType;

typedef struct		//定义一个顺序栈的结构(封装体)
{
	SElemType* base;
	SElemType* top;
	int stacksize;
}SqStack;

Status InitStack(SqStack& S)		//1. 顺序栈的初始化
{
	S.base = new SElemType[MAXSIZE];
	if (!S.base) return OVERFLOW;
	S.top = S.base;
	S.stacksize = MAXSIZE;
	return OK;
}

bool StackEmpty(SqStack S)		//2. 判断顺序栈是否为空
{
	if (S.top == S.base) return true;
	else return false;
}

int StaticLength(SqStack S)		//3. 判断顺序栈的长度
{
	return S.top - S.base;
}

Status ClearStack(SqStack S)		//4. 清空顺序栈
{
	if (S.base) S.top = S.base;
	return OK;
}

Status DestroyStack(SqStack& S)		//5. 销毁顺序栈
{
	if (S.base) {
		delete S.base;
		S.stacksize = 0;
		S.base = S.top = NULL;
	}
	return OK;
}

Status Push(SqStack& S, SElemType e)		//6. 顺序栈入栈
{
	if (S.top - S.base == S.stacksize)		//满了
		return ERROR;
	*S.top++ = e;		//先赋值,再加
	return OK;
}

Status Pop(SqStack& S, SElemType& e)		//7. 顺序栈出栈
{
	if (S.top == S.base)		//栈空
		return ERROR;
	e = *--S.top;
	return OK;
}

Status GetTop(SqStack S, SElemType e)		//8. 取顺序栈顶元素
{
	if (S.top == S.base)		//栈空
		return ERROR;
	e = *(S.top - 1);
	return OK;
}

3. 代码分析

1)主函数内容分析

  1. 主函数我主要用了while语句,它形成的作用是完成一个操作后程序不会退出,问你继续哪步操作,除非你按下0该程序才会结束,并显示一个万能提示:
    在这里插入图片描述

当然这里需要设置一个信号量choose(注意看一下它是有初值的),判断choose是否为0,以便于随时退出程序。

  1. 一个有意思的地方在于我我弄了一个很贱的操作(嘿嘿嘿)
		do {
			cin >> choose;
			if (choose < 0 || choose>8)
				cout << "您输入的信息不在本次服务之内,请重新输入:" << endl;
		} while (choose < 0 || choose>8);

emmm……,它的意思就是说如果你不选择我给你设定的那几个数,你就甭想从我这里过去,对,就是这么干,不过值得注意的是do-while语句可以用来写选择提示性语句,很好使,对了,while后边括号里是条件为真的判断(真的才能继续执行循环),我每次到这里总弄错,给你借鉴一下。

  1. 其他要注意的地方就是case里要写break,很容易忘,主函数就介绍这么多。

2)basic.h文件分析

  1. 定义一个结构体,这里就不多说了,不过你要是想继续扩展的话可以自愿添加元素,比如我这里只设定了姓名和学号两类:
typedef struct		//定义一个的结构体
{
	char name[30];		//姓名
	char mumber[30];		//学号
}SElemType;

可能你要问为什么学号我也用char类型,呃,你问到我的痛处了。。。
在这里插入图片描述
开始我也设置的是int型,但最后运行程序的时候总是出现死循环,九牛二虎之力后才发现是这里溢出的原因,
如果我输入的学号是311608070508,嗯,毫无疑问,这都多大的数了,int放不下,而且我也不建议用unsigned int,以及long int,为什么呢?因为划不来:

  • 学号不用参与数值计算,把它当做数值的话浪费空间和脑力;
  • char型可以存放好多好多好多位学号,还不占用大面积存储空间;

所以,我果断选择了char number[30] (我特么就不信谁的学号有三十位数,超神学院的吧)

  1. 定义一个顺序栈
typedef struct		//定义一个顺序栈的结构(封装体)
{
	SElemType* base;
	SElemType* top;
	int stacksize;
}SqStack;

顺序栈定义很简单,就俩指针,一个指向顶端,一个指向底端,但要注意的是:top指的是栈顶元素之上的下标地址在这里插入图片描述
这个很好理解,如果base=0的话,那top=3,元素的个数就很容易求出来了:
stacksize=top-base;

  1. 接下来就是顺序栈的初始化、判断它是否为空、求长度、清空顺序栈、销毁顺序栈、顺序栈入栈、顺序栈出栈、取顺序栈顶元素,

是不是感觉妈呀,真多,你要是这么感觉的话,那我只能说:
在这里插入图片描述
确实不多,就不要吓自己咯,这些全是一个个函数而已,用的时候调用一下就行了。不过重点我给大家总结了一下几点:

  • 当S.top == S.base,即两个指针相遇的时候,就意味着这个栈是空的
  • 销毁顺序栈的时候用了一个if语句:
 if (S.base) {}
	return OK;

为什么只写了S.base呢,if语句又该怎么判断呢?注意:S.base是一个指针,这里是判断S.base是否为 NULL

  • 线性栈入栈和出栈的时候我分别用了*S.top++ = e;和e = *–S.top; ,注意看程序里我写的注释,到底是先加、减,还是先赋值
  • 输入的时候注意,因为我的结构体有两项元素,所以在main函数里我的输入是这样的:
cin >> e.name>> e.mumber;

如果你扩展了结构体其他的元素,记得输入的时候也要输进去;

  • 最后来一个完美的return 0 就告一段落了。

4. 运行结果

在这里插入图片描述
嗯,这才是世界应有的样子,就到这里,撂了。

  • 6
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值