数据结构(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;
}

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

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

相关文章

2024-2-9-复习作业

1> 要求&#xff1a; 源代码&#xff1a; CCgcc EXEa.out OBJS$(patsubst %.c,%.o,$(wildcard *.c)) CFLAGS-c -oall:$(EXE)$(EXE):$(OBJS)$(CC) $^ -o $%.o:%.c$(CC) $(CFLAGS) $ $^.PHONY:cleanclean:rm $(OBJS) $(EXE) 效果图&#xff1a; 2> 要求&#xff1a; 源…

【JAVA WEB】标签的应用

个人简历信息填写界面 通过上篇博客对java web标签的介绍&#xff0c;这里我们简单的应用一下这些标签。 效果 代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content&q…

c#cad 创建-点(六)

运行环境 vs2022 c# cad2016 调试成功 一、代码说明 创建一个点的命令方法。代码的主要功能是在当前活动文档中创建一个点&#xff0c;并将其添加到模型空间块表记录中。 代码的主要步骤如下&#xff1a; 获取当前活动文档、数据库和编辑器对象。使用事务开始创建点的过程…

【开源】JAVA+Vue.js实现高校实验室管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容2.1 实验室类型模块2.2 实验室模块2.3 实验管理模块2.4 实验设备模块2.5 实验订单模块 三、系统设计3.1 用例设计3.2 数据库设计 四、系统展示五、样例代码5.1 查询实验室设备5.2 实验放号5.3 实验预定 六、免责说明 一、摘…

AWS配置内网EC2服务器上网【图形化配置】

第一种方法&#xff1a;创建EC2选择启用分配公网ip 1. 创建vpc 2. 创建子网 3. 创建互联网网关 创建互联网网关 创建互联网网关 &#xff0c;设置名称即可 然后给网关附加到新建的vpc即可 4. 给新建子网添加路由规则&#xff0c;添加新建的互联网网关然后点击保存更改 5. 新建…

vue3项目实现预览图片、旋转图片功能

一、需求&#xff1a; 在点击图片时&#xff0c;能预览大图&#xff0c;弹出一个包含旋转图片功能按钮的弹窗。用户可通过点击按钮实现对图片的旋转操作 二、思路&#xff1a; 点击图片预览&#xff1a; 用户通过点击图片触发预览功能。接收图片的 URL&#xff0c;弹出一个模…

Vue-Vue3 集成编辑器功能

1、安装依赖 编辑器插件需要安装 wangeditor/editor 和 wangeditor/editor-for-vue 两个插件 npm install wangeditor/editor --savevue3运行如下命令安装 npm install wangeditor/editor-for-vuenext --savevue2运行如下命令安装 npm install wangeditor/editor-for-vue -…

云计算运维1

1、企业服务器LNMP环境搭建 集群&#xff1a;多台服务器在一起作同样的事 。分布式 &#xff1a;多台服务器在一起作不同的事 。 环境准备&#xff1a; 1、设置静态ip&#xff08;NAT模式网关为.2&#xff09; # cat /etc/sysconfig/network-scripts/ifcfg-ens33 TYPE"E…

Stable Diffusion 模型下载:majicMIX realistic 麦橘写实 - V7

文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八案例九案例十下载地址模型介绍 非常推荐的一个写实模型,由国人“Merjic”发布,下载量颇高。这款大模型带来非常高的写实度以及光影感,特别是光线在画面中生成的感觉,也相比其他的人物大模型带来…

查看NodeJs版本和查看NPM版本

Windows10 Dos命令下 查看NodeJs版本和查看NPM版本 NodeJs的命令是&#xff1a;node -v Npm的命令是&#xff1a;npm -v 下图&#xff1a; 记录下&#xff01;~

Leetcode—61. 旋转链表【中等】

2024每日刷题&#xff08;114&#xff09; Leetcode—61. 旋转链表 实现代码 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(nullptr) …

springboot微信小程序uniapp学习计划与日程管理系统

基于springboot学习计划与日程管理系统&#xff0c;确定学习计划小程序的目标&#xff0c;明确用户需求&#xff0c;学习计划小程序的主要功能是帮助用户制定学习计划&#xff0c;并跟踪学习进度。页面设计主要包括主页、计划学习页、个人中心页等&#xff0c;然后用户可以利用…

C++分支语句

个人主页&#xff1a;PingdiGuo_guo 收录专栏&#xff1a;C干货专栏 大家新年快乐&#xff0c;今天&#xff0c;我们来了解一下分支语句。 文章目录 1.什么是分支语句 1.if语句 基本形式 用法说明 练习 2.if-else语句 基本形式 用法说明 练习 3.switch语句 基本形式…

生成验证码-超简单

引言 在Web开发中&#xff0c;验证码是一种常见的防止恶意破解、自动化提交的有效手段。在Java项目中&#xff0c;我们可以使用Hutool工具库快速实现验证码功能。Hutool是一个Java工具包&#xff0c;它以简洁易用著称&#xff0c;其中包含了验证码模块&#xff0c;可以让我们轻…

【RPA】智能自动化的未来:AI + RPA

伴随着人工智能&#xff08;AI&#xff09;技术的迅猛进步&#xff0c;机器人流程自动化&#xff08;RPA&#xff09;正在经历一场翻天覆地的变革。AI为RPA注入了新的活力&#xff0c;尤其在处理复杂任务和制定决策方面。通过融合自然语言处理&#xff08;NLP&#xff09;、机器…

Codeforces Round 260 (Div. 1)A. Boredom(dp)

最开始写了一发贪心wa了&#xff0c;然后这种选和不选的组合优化问题&#xff0c;一般是考虑动态规划 d p [ i ] [ 0 ] &#xff1a; dp[i][0]&#xff1a; dp[i][0]&#xff1a;表示第i个数不选的最大值 d p [ i ] [ 1 ] &#xff1a; dp[i][1]&#xff1a; dp[i][1]&#xf…

sql相关子查询

1.什么是相关子查询 相关子查询是一个嵌套在外部查询中的查询&#xff0c;它使用了外部查询的某些值。每当外部查询处理一行数据时&#xff0c;相关子查询就会针对那行数据执行一次&#xff0c;因此它的结果可以依赖于外部查询中正在处理的行。 2.为什么要使用相关子…

C++面试宝典第27题:完全平方数之和

题目 给定正整数 n,找到若干个完全平方数(比如:1、4、9、16、...),使得它们的和等于n。你需要让组成和的完全平方数的个数最少。 示例1: 输入:n = 12 输出:3 解释:12 = 4 + 4 + 4。 示例2: 输入:n = 13 输出:2 解释:13 = 4 + 9。 解析 这道题主要考察应聘者对于…

Java风暴:打造高效作家信息管理平台

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

每日OJ题_位运算①_位运算解题方法+3道OJ

目录 位运算算法原理 ①力扣191. 位1的个数 解析代码 ②力扣338. 比特位计数 解析代码 ③力扣461. 汉明距离 解析代码 位运算算法原理 常见位运算解题方法&#xff1a; 1. 基础位运算&#xff1a; &&#xff1a;按位与&#xff0c;有0就是0 | &#xff1a;按位或&a…