数据结构(C语言)代码实现(八)——顺序栈实现数值转换行编辑程序括号分配汉诺塔

目录

 参考资料

顺序栈的实现

头文件SqStack.h(顺序栈函数声明)

源文件SqStack.cpp(顺序栈函数实现)

顺序栈的三个应用

数值转换

行编辑程序

顺序栈的实现测试

栈与递归的实现(以汉诺塔为例)


 参考资料

1.本文文章结构参考这篇博客,部分代码也引用自这篇博客。

2021-9-22【数据结构/严蔚敏】【顺序栈&链式栈&迷宫求解&表达式求值】【代码实现算法3.1-3.5】_数据结构表达式求值代码严老师-CSDN博客

2.又搜到一个更靠谱的,这个的引用也用指针替代了。

栈和队列-数据结构与算法(C语言版)_调用pop(&s,&e)函数,让队头数据出队,赋值给参数e,printf输出e-CSDN博客3. 数据结构课本严蔚敏版。

顺序栈的实现

头文件SqStack.h(顺序栈函数声明)

#pragma once
#include <cstdio>
#include <cstdlib>
#include <cstring>

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;//Status是函数的类型,其值是函数结果状态代码
typedef int SElemType;

//-----栈的顺序存储表示-----
#define STACK_INIT_SIZE 100  //存储空间初始分配量
#define STACKINCREMENT 10    //存储空间分配增量
typedef struct SqStack {
	SElemType* base;//在栈构造之前和销毁之后,base的值为NULL
	SElemType* top; //栈顶指针
	int stacksize;  //当前已分配的存储空间,以元素为单位
}SqStack;
//-----基本操作的函数原型说明-----
Status InitStack(SqStack& S);
//构造一个空栈S
Status DestroyStack(SqStack& S);
//销毁栈S,S不再存在
Status ClearStack(SqStack& S);
//把S置为空栈
Status StackEmpty(SqStack S);
//若栈S为空栈,则返回TRUE,否则返回FALSE
int StackLength(SqStack S);
//返回S的元素个数,即栈的长度
Status GetTop(SqStack S, SElemType& e);
//若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR
Status Push(SqStack& S, SElemType e);
//插入元素e为新的栈顶元素
Status Pop(SqStack& S, SElemType& e);
//若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR
Status StackTraverse(SqStack S, void(*visit)(SElemType));
//从栈顶到栈底依次对栈中每个元素调用函数visit()。一旦visit()失败,则操作失败

源文件SqStack.cpp(顺序栈函数实现)

源文件SqStack.cpp是头文件SqStack.h的实现。

#include "SqStack.h"

//-----基本操作的函数算法描述(部分)-----
Status InitStack(SqStack& S) {
	//构造一个空栈S
	S.base = (SElemType*)malloc(STACK_INIT_SIZE * sizeof(SElemType));
	if (!S.base)exit(OVERFLOW);//存储分配失败,警告C6011
	S.top = S.base;
	S.stacksize = STACK_INIT_SIZE;
	return OK;
}

Status DestroyStack(SqStack& S) {
	free(S.base);
	S.top = S.base = NULL;
	S.stacksize = 0;
	return OK;
}

Status ClearStack(SqStack& S) {
	if (!S.base)return ERROR;
	S.top = S.base;
	return OK;
}

Status StackEmpty(SqStack S) {
	if (S.base == S.top)
		return OK;
	return ERROR;
}

int StackLength(SqStack s) {
    if (!s.base)
        return ERROR;
    return (int)(s.top - s.base);
}

Status GetTop(SqStack s, SElemType& e) {
    //若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR
    if (s.base == s.top)
        return ERROR;
    e = *(s.top - 1);
    return OK;
}

Status Push(SqStack& s, SElemType e) {
    //插入元素e为新的栈顶元素
    if (!s.base)return ERROR;
    if (s.top - s.base >= s.stacksize) {//栈满,追加存储空间
        s.base = (SElemType*)realloc(s.base, (s.stacksize + STACKINCREMENT) * sizeof(SElemType));
        if (!s.base)exit(_OVERFLOW);//存储分配失败
        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) {
    //若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR
    if (!s.base || s.top == s.base) return ERROR;
    e = *--s.top;//--s.top; e=*s.top;
    return OK;
}

Status StackTraverse(SqStack s, void (*visit)(SElemType)) {
	SElemType* p = s.base;
	if (!s.base)return ERROR;
	while (p < s.top)
		visit(*p++);
	printf("\n");
	return OK;
}

顺序栈的四个应用

数值转换

源文件conversion.cpp

#include "SqStack.h"

void conversion() {
	//对于输入的任意一个非负十进制整数,打印输出与其等值的八进制数
	SqStack S;
	InitStack(S);//构造空栈
	SElemType N,e;
	scanf_s("%d", &N);
	if (N == 0)//当N为0时下面的while循环不输出
	{
		printf("%d", N);
		return;
	}
	while (N) {
		Push(S, N % 8);
		N = N / 8;
	}
	while (!StackEmpty(S)) {
		Pop(S, e);
		printf("%d", e);
	}
}
int main()
{
	conversion();
	return 0;
}//算法3.1

测试结果(课本样例)

括号匹配

栈和队列-数据结构与算法(C语言版)_调用pop(&s,&e)函数,让队头数据出队,赋值给参数e,printf输出e-CSDN博客源文件 MatchBrackets.cpp

完整代码

#include "SqStack.h"

/*
 * 括号匹配
 * 注意将ElemType 修为 char
 */
Status MatchBrackets(SqStack& S, char* brackets) {
    SElemType ch;
    int len = strlen(brackets);
    for (int i = 0; i < len; i++) {
        if (brackets[i] == '{' || brackets[i] == '[' || brackets[i] == '(') {
            Push(S, brackets[i]);
        }
        if (brackets[i] == '}' || brackets[i] == ']' || brackets[i] == ')') {

            if (StackEmpty(S)) {
                printf("右括号多于左括号\n");
                return ERROR;
            }
            else {
                GetTop(S, ch);
                if (ch == '{' && brackets[i] == '}' || ch == '[' && brackets[i] == ']' || ch == '(' && brackets[i] == ')') {
                    Pop(S, ch);
                }
            }

        }
    }
    if (!StackEmpty(S))
        printf("左括号多于右括号\n");
    else
        printf("括号匹配成功!");
    return OK;
}

int main()
{
    SqStack S;
    char brackets[81] = { 0 };
    //用char* brackets;会报错
    InitStack(S);
    scanf_s("%s", brackets,sizeof(brackets));
    //不知道为什么,不加sizeof(),括号匹配函数len一直为0,
    //导致输出总是“括号匹配成功”。
    MatchBrackets(S, brackets);
    return 0;
}

 测试结果

行编辑程序

源文件LineEdit.cpp

本来想两个主函数能不能在同一个工程下运行,结果不可以。接着我把数值转换这个主函数移除,发现可以运行行编辑程序这个代码了。

右键conversion.cpp,点击移除。

接着打开LineEdit.cpp。右键点击源文件,在添加中找到现有项,点击现有项寻找即可(前提是你写了)

下面是完整代码

#include "SqStack.h"

void visit(SElemType e) {
	printf("%d ", e);
}

void LineEdit() {
	//利用字符栈S,从终端接收一行并传送至调用过程的数据区
	SqStack S;
	InitStack(S);//构造空栈S
	SElemType c;
	char ch = getchar();//从终端接收第一个字符
	while (ch != EOF) {//EOF为全文结束符,Ctrl+z+回车键对应EOF
		while (ch != EOF && ch != '\n') {//一行内
			switch (ch) {
			case'#':Pop(S, c);
				break;//仅当栈非空时退栈
			case'@':ClearStack(S);
				break;//重置S为空栈
			default:Push(S, ch);
				break;//有效字符进栈,未考虑栈满情形
			}
			ch = getchar();//从终端接收下一个字符
		}
		//将从栈底到栈顶的栈内字符传送至调用过程中的数据区
		StackTraverse(S, visit);//课本没有,但我看不到结果,便加上了这个函数
		ClearStack(S);//重置S为空栈
		if (ch != EOF)ch = getchar();
	}
	DestroyStack(S);
}
int main()
{
	LineEdit();
	return 0;
}

测试样例选自课本P49页右下角两行字符,测试结果如下:

此时正常返回。从元素个数看,结果正确,但不直观,所以将SElemType改为char类型。

为了实现行编辑程序,特别修改两处代码(仅在行编辑程序中使用)。

typedef char SElemType;//修改SqStack.h第13行

void visit(SElemType e) {
	printf("%c", e);
}//修改LineEdit.cpp第4行

最终结果 

顺序栈的实现测试

源文件test.cpp ,这个是我复制粘贴的我参考的博客。

#include "SqStack.h"
#include <iostream>
using namespace std;

void visit(SElemType e) {
	printf("%d ", e);
}
//简单测试主函数
int main() {
	SqStack s;
	cout << "InitStack" << endl;
	InitStack(s);
	cout << "StackEmpty" << endl;
	StackEmpty(s) ? cout << "yes\n" : cout << "no\n";
	cout << "Push" << endl;
	for (int i = 1; i <= 6; i++)
		Push(s, i);
	cout << "StackTraverse" << endl;
	StackTraverse(s, visit);
	cout << "StackLength" << endl;
	cout << StackLength(s) << endl;
	cout << "Pop" << endl;
	SElemType e;
	Pop(s, e);
	cout << e << endl;
	StackTraverse(s, visit);
	cout << "GetTop" << endl;
	GetTop(s, e);
	cout << e << endl;

	return 0;
}

测试结果

栈与递归的实现(以汉诺塔为例)

这里课本的代码没有用栈实现递归,但一直在强调递归函数是通过栈实现的,并从栈的角度解释了递归函数的原理。

源文件hanoi.cpp

#include <cstdio>
#include <cstdlib>
#include <cstring>

int C = 0;
void move(char x, int n, char z) {
	printf("%d. Move disk %d from %c to %c\n", ++C, n, x, z);
}
void hanoi(int n, char x, char y, char z)
//将塔座x上按直径由小到大且自上而下编号为1至n的n个圆盘按规则搬到
//塔座z上,y可用作辅助塔座。
//搬动操作move(x, n, z) 可定义为(c是初值为0的全局变量,对搬动计数):
//printf(" %i. Move disk %i from %c to %c\n", ++c, n, x, z);
{
	if (n == 1)
		move(x, 1, z);//将编号为1的圆盘从x移到z
	else {
		hanoi(n - 1, x, z, y);//将x上编号为1至n-1的圆盘移到y,z作辅助塔
		move(x, n, z);        //将编号为n的圆盘从x移到z
		hanoi(n - 1, y, x, z);//将y上编号为1至n-1的圆盘移到z,x做辅助塔
	}
}
int main()
{
	int n=3;
	char A='a', B='b', C='c';
	hanoi(n, A, B, C);
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/379900.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

预测模型:MATLAB线性回归

1. 线性回归模型的基本原理 线性回归是统计学中用来预测连续变量之间关系的一种方法。它假设变量之间存在线性关系&#xff0c;可以通过一个或多个自变量&#xff08;预测变量&#xff09;来预测因变量&#xff08;响应变量&#xff09;的值。基本的线性回归模型可以表示为&…

【03】C++ 类和对象 2:默认成员函数

文章目录 &#x1f308; 前言&#x1f308; Ⅰ 构造函数1. 构造函数概念2. 构造函数特性3. 初始化列表 &#x1f308; Ⅱ 析构函数1. 析构函数概念2. 析构函数特性 &#x1f308; Ⅲ 拷贝构造1. 拷贝构造概念2. 拷贝构造特性3. 深度拷贝构造 &#x1f308; Ⅳ 赋值重载1. 运算符…

Selenium自动化测试框架的搭建

说起自动化测试&#xff0c;我想大家都会有个疑问&#xff0c;要不要做自动化测试&#xff1f; 自动化测试给我们带来的收益是否会超出在建设时所投入的成本&#xff0c;这个嘛别说是我&#xff0c;即便是高手也很难回答&#xff0c;自动化测试的初衷是美好的&#xff0c;而测试…

【Linux】vim的基本操作与配置(下)

Hello everybody!今天我们继续讲解vim的操作与配置&#xff0c;希望大家在看过这篇文章与上篇文章后都能够轻松上手vim! 1.补充 在上一篇文章中我们说过了&#xff0c;在底行模式下set nu可以显示行号。今天补充一条&#xff1a;set nonu可以取消行号。这两条命令大家看看就可…

SpringCloud-Ribbon:负载均衡(基于客户端)

6. Ribbon&#xff1a;负载均衡(基于客户端) 6.1 负载均衡以及Ribbon Ribbon是什么&#xff1f; Spring Cloud Ribbon 是基于Netflix Ribbon 实现的一套客户端负载均衡的工具。简单的说&#xff0c;Ribbon 是 Netflix 发布的开源项目&#xff0c;主要功能是提供客户端的软件负…

JRebel激活-nginx版本

nginx转发流量&#xff08;代替其他网上说的那个工具&#xff09; proxy_pass http://idea.lanyus.com; 工具激活 填写内容说明&#xff1a; 第一行的激活网址是&#xff1a;http://127.0.0.1:8888/ 正确的GUID。GUID 可以通过专门的网站来生成&#xff08;点击打开&#…

Redis事务和Redis管道

文章目录 1.Redis事务1.1 Redis事务是什么&#xff0c;能干嘛&#xff1f;1.2 Redis事务和数据库事务的差异1.3 Redis事务的相关命令 2.Redis管道2.1 Redis管道是什么2.2 管道与原生批量命令对比2.3 管道与事务对比2.4 使用管道注意事项 1.Redis事务 1.1 Redis事务是什么&…

机器学习:分类决策树(Python)

一、各种熵的计算 entropy_utils.py import numpy as np # 数值计算 import math # 标量数据的计算class EntropyUtils:"""决策树中各种熵的计算&#xff0c;包括信息熵、信息增益、信息增益率、基尼指数。统一要求&#xff1a;按照信息增益最大、信息增益率…

c++随机数生成进阶random与随之种子生成器的使用

随机数的作用我就不说了&#xff0c;但凡要用随机数的童鞋一定是有这个需求。下面我们就分三个层次来介绍随机数生成。 文章目录 一、利用rand函数生成随机数1、rand裸奔2、随机数种子srand-随机数生成器3、如何得到不同的种子值&#xff08;1&#xff09;、利用系统时间戳tim…

文件上传-Webshell

Webshell简介 webshell就是以aspphpjsp或者cgi等网页文件形式存在的一种命令执行环境&#xff0c;也可以将其称做为一种网页木马后门。 攻击者可通过这种网页后门获得网站服务器操作权限&#xff0c;控制网站服务器以进行上传下载文件、查看数据库、执行命令等… 什么是木马 …

2024.02.08

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget) {ui->setupUi(this);this->setWindowIcon(QIcon(":/zh.png"));ui->lineEdit->setPlaceholderText("账号/手…

【Linux笔记】缓冲区的概念到标准库的模拟实现

一、缓冲区 “缓冲区”这个概念相信大家或多或少都听说过&#xff0c;大家其实在C语言阶段就已经接触到“缓冲区”这个东西&#xff0c;但是相信大家在C语言阶段并没有真正弄懂缓冲区到底是个什么东西&#xff0c;也相信大家在C语言阶段也因为缓冲区的问题写出过各种bug。 其…

再识C语言 DAY16【进制的转换 】

文章目录 前言进制的转换一、各个进制的组成二、二进制转换其他进制三。其他进制转换为二进制四.小数部分进制转换五.八进制与十进制的相互转换 总如果您发现文章有错误请与我留言&#xff0c;感谢 前言 本文章总结于此视频 进制的转换 一、各个进制的组成 1. 二进制&#x…

【C语言自定义类型详解进阶】结构体(补充结构体的对齐和位段,一口气看完系列,央妈都点赞的博文)

目录 1.结构体 1.1 结构的基础知识 1.2 结构的声明 1.2.1特殊的声明&#xff08;匿名结构体类型&#xff09; 1.3结构体变量的定义 1.4关于匿名结构体类型的补充 1.5结构体的自引用 1.6结构体变量的初始化 2.结构体内存对齐&#xff08;重点&#xff09; 2.1偏移量补…

报错ValueError: Unknown CUDA arch (8.6) or GPU not supported

文章目录 问题描述解决方案参考文献 问题描述 报错 ValueError: Unknown CUDA arch (8.6) or GPU not supported 本人显卡为 RTX 3060&#xff0c;CUDA 为 10.2&#xff0c;PyTorch 为 1.5 解决方案 修改 C:\Users\Administrator\Envs\test\Lib\site-packages\torch\utils\c…

nvm安装nodejs 报错certificate has expired or is not yet valid

今天在使用nvm安装nodejs时&#xff0c;突然报如下错误&#xff1a; 从报错信息中很容易知道这是因为镜像凭证过期&#xff0c;所以我们只需要换个镜像即可。 打开你nvm的安装目录下的settings.txt文件&#xff0c;将下面两行添加到里面&#xff0c;如果已经有的就覆盖。 nod…

【制作100个unity游戏之24】unity制作一个3D动物AI生态系统游戏3(附项目源码)

最终效果 文章目录 最终效果系列目录前言随着地面法线旋转在地形上随机生成动物不同部位颜色不同最终效果源码完结系列目录 前言 欢迎来到【制作100个Unity游戏】系列!本系列将引导您一步步学习如何使用Unity开发各种类型的游戏。在这第24篇中,我们将探索如何用unity制作一…

一周学会Django5 Python Web开发-Django5创建项目(用命令方式)

锋哥原创的Python Web开发 Django5视频教程&#xff1a; 2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~共计11条视频&#xff0c;包括&#xff1a;2024版 Django5 Python we…

前端滚动组件分享

分享一个前端可视化常用的卡片列表滚动组件&#xff0c;常用于可视化项目左右两侧的卡片列表的滚动。效果如下图所示&#xff1a; 组件描述 当鼠标移入滚动区域时&#xff0c;滚动行为停止当鼠标再次离开时&#xff0c;滚动继续 源码展示 <template><div ref"…

停车场|基于Springboot的停车场管理系统设计与实现(源码+数据库+文档)

停车场管理系统目录 目录 基于Springboot的停车场管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、管理员功能实现 &#xff08;1&#xff09;车位管理 &#xff08;2&#xff09;车位预订管理 &#xff08;3&#xff09;公告管理 &#xff08;4&#…