数据结构——实验二·栈

news2025/1/23 12:13:00

海~~欢迎来到Tubishu的博客🌸如果你也是一名在校大学生,正在寻找各种变成资源,那么你就来对地方啦🌟
Tubishu是一名计算机本科生,会不定期整理和分享学习中的优质资源,希望能为你的编程之路添砖加瓦⭐🔥
当然,如果你也好的资源推荐,欢迎在评论区分享,让我们共同打造一个丰富的编程资源库!🔥
本文专栏 ➡️ 数据结构

实验目的:

  • 掌握栈的顺序/链式存储结构
  • 掌握栈的操作特性
  • 掌握基于顺序栈/链栈的基本操作的实现方法

实验内容:

(1)建立一个空栈
(2)对已建立的栈进行插入、删除、取栈顶元素等基本操作


顺序栈操作

实验产出:

1.问题分析:
栈满问题:需要预先定义栈的最大容量,并在入栈时进行检查。
栈空问题:需要在出栈时进行检查,避免栈空时弹出元素。
内存管理:顺序栈使用数组实现,不需要动态分配内存,但需要注意栈的最大容量。

2.算法设计:
初始化:创建一个顺序栈,定义栈的最大容量(1024)。
入栈(Push_Sq):检查栈是否满,若不满则将元素压入栈顶,并更新栈顶指针。
出栈(Pop_Sq):检查栈是否空,若不空则将栈顶元素弹出,并更新栈顶指针。
判断栈空(StackEmpty_Sq):检查栈顶指针是否指向栈底。
判断栈满(StackFull_Sq):检查栈顶指针是否达到栈的最大容量。

3.核心代码:

#include <stdio.h>
#include <stdlib.h>

#define ERROR 0
#define OK 1

#define MAXSIZE 4
typedef char SElemType;

typedef struct SeqStack {
    SElemType data[MAXSIZE];
    int top;
} SeqStack;

// 顺序栈的初始化
int InitStack_Sq(SeqStack *&S) {
    S = new SeqStack;
    if (!S) // 存储分配失败
        return ERROR;
    S->top = 0;
    return OK;
}

// 销毁顺序栈
int DestroyStack_Sq(SeqStack *&S) {
    if (!S) // 顺序栈为空
        return ERROR;
    delete S;
    S = NULL;
    return OK;
}

// 清空顺序栈
void ClearStack_Sq(SeqStack *&S) {
    S->top = 0;
}

// 判断顺序栈是否为空
int StackEmpty_Sq(SeqStack *S) {
    return S->top == 0;
}

// 判断顺序栈是否已满
int StackFull_Sq(SeqStack *S) {
    return S->top >= MAXSIZE;
}

// 入栈操作
int Push_Sq(SeqStack *S, SElemType e) {
    if (StackFull_Sq(S)) return ERROR; // 栈已满
    S->data[S->top++] = e;
    return OK;
}

// 出栈操作
int Pop_Sq(SeqStack *S, SElemType &e) {
    if (StackEmpty_Sq(S)) return ERROR; // 栈空
    e = S->data[--S->top];
    return OK;
}

// 取栈顶元素
int GetTop_Sq(SeqStack *S, SElemType &e) {
    if (StackEmpty_Sq(S)) return ERROR; // 栈空
    e = S->data[S->top - 1];
    return OK;
}

// 输出栈顶元素/输出顺序栈 
void DispStack_Sq(SeqStack *S) {
    if (StackEmpty_Sq(S)) {
        printf("栈空\n");
    } else {
        printf("栈顶元素为:%c\n", S->data[S->top - 1]);
        printf("顺序栈:"); 
        char p = S->top;
		while(p!=0)
			printf("%c ", S->data[--p]);
		printf("\n"); 
    }
}


// 显示菜单
void showmenu() {
    printf("\n\n\n");
    printf("*       --顺序栈基本运算演示--         *\n");
    printf("****************************************\n");
    printf("*       1-------顺序栈的初始化         *\n");
    printf("*       2-------销毁顺序栈             *\n");
    printf("*       3-------清空顺序栈             *\n");
    printf("*       4-------判断顺序栈是否为空     *\n");
    printf("*       5-------判断顺序栈是否已满     *\n");
    printf("*       6-------入栈操作               *\n");
	printf("*       7-------出栈操作               *\n");
	printf("*       8-------取栈顶元素             *\n");
	printf("*                                      *\n");
    printf("*       0-------退出                   *\n");
    printf("****************************************\n");
}

void Stack_Sq() {
    char choice = 'N';
    SElemType item;
    
    SeqStack* S;
    int flag = 0; // 是否创建好了顺序栈
    
    while (choice != '0') {
    	printf("\n请选择菜单号(0--8):");
        scanf(" %c", &choice);
        switch (choice) {
            case '1':
                printf("初始化顺序栈操作\n");
                if (InitStack_Sq(S)) {
                    printf("初始化成功!\n");
                    flag = 1; // 标志顺序栈的存在
                } else {
                    printf("初始化失败!\n");
                }
                break;
                
            case '2':
                if (flag) { // 顺序栈存在
                    DestroyStack_Sq(S);
                    flag = 0; // 顺序栈已删除
                    printf("顺序栈删除成功!\n");
                } else {
                    printf("顺序栈不存在,操作失败!\n");
                }
                break;
                
            case '3':
                if (flag) { // 顺序栈存在
                    ClearStack_Sq(S);
                    printf("顺序栈清空成功!\n");
                    DispStack_Sq(S); // 输出顺序栈 
                } else {
                    printf("顺序栈不存在,操作失败!\n");
                }
                break;
                
            case '4':
				if (flag) { // 顺序栈存在
				    printf("顺序栈%s\n", StackEmpty_Sq(S) ? "空" : "不空");
				    DispStack_Sq(S); // 输出顺序栈 
				} else {
				    printf("顺序栈不存在,操作失败!\n");
				}
				break;
				
			case '5':
				if (flag) { // 顺序栈存在
				    printf("顺序栈%s\n", StackFull_Sq(S) ? "满" : "不满");
				    DispStack_Sq(S); // 输出顺序栈 
				} else {
				    printf("顺序栈不存在,操作失败!\n");
				}
				break;	
				
			case '6':
				if (flag) { // 顺序栈存在
				    printf("请输入要入栈的元素的值:");
				    scanf(" %c", &item);
				    if (Push_Sq(S, item))
				        printf("该元素已入栈\n");
				    else {
				        printf("栈满,入栈操作失败!\n");
				    }
				    DispStack_Sq(S); // 输出顺序栈 
				} else {
				    printf("顺序栈不存在,操作失败!\n");
				}
				break;
				
			case '7':
				if (flag) { // 顺序栈存在
				    if (Pop_Sq(S, item))
				        printf("出栈元素为:%c\n", item);
				    else
				        printf("栈空!\n");
				    DispStack_Sq(S); // 输出顺序栈 
				} else {
				    printf("顺序栈不存在,操作失败!\n");
				}
				break;
				
			case '8':
				if(flag){//顺序栈存在 
					if (GetTop_Sq(S, item));
					    //printf("栈顶元素为:%c\n", item);
					else
					    printf("栈空!\n");
					DispStack_Sq(S); // 输出顺序栈 
				} else {
				    printf("顺序栈不存在,操作失败!\n");
				}
				break;
				
			case '0':
				printf("程序结束!\n");
				DestroyStack_Sq(S);
				break;
				
			default:
				printf("选择错误,请重新输入!\n");
				break;
			}
		}
	}
	
int main() {
	showmenu();
    Stack_Sq();
    return 0;
}

4.运行结果:
在这里插入图片描述在这里插入图片描述

5.调试:
栈满测试:
尝试向顺序栈中压入超过预定义的最大容量(例如,超过4个元素),验证程序是否能够正确检测到栈满并输出相应的提示信息。
预期结果:程序应提示“栈满”并阻止进一步的入栈操作。
栈空测试:
尝试从空栈中弹出元素,验证程序是否能够正确检测到栈空并输出相应的提示信息。
预期结果:程序应提示“栈空”并阻止弹出操作。
边界条件测试:
入栈一个元素后立即出栈,验证栈顶指针是否正确更新。
预期结果:栈顶指针应正确指向栈底(-1),且程序能够正确处理空栈状态。


链栈操作

实验产出:

1.问题分析:
内存分配和释放:需要在入栈时动态分配内存,在出栈时释放内存,避免内存泄漏。
栈空问题:需要在出栈时进行检查,避免栈空时删除结点。
指针操作:需要注意指针的正确使用,避免出现野指针或内存泄漏。

2.算法设计:
初始化:创建一个头结点,初始化栈顶指针。
入栈:创建一个新结点,将其插入到链表的头部,并更新栈顶指针。
出栈:检查栈是否空,若不空则删除链表的头部结点,并更新栈顶指针。
判断栈空:检查栈顶指针是否指向头结点。

3.核心代码:

#include <stdio.h>
#include <stdlib.h>

#define ERROR 0
#define OK 1

typedef char SElemType;

// 定义链栈节点
typedef struct Node {
    SElemType data; // 数据域
    struct Node *next; // 指针域
} STackNode, *LinkStack;

// 初始化链栈
int InitStack_L(LinkStack &top) {
    top = new STackNode;
    if (!top) return ERROR; // 内存分配失败
    top->next = NULL;
    return OK;
}

// 销毁链栈
int DestroyStack_L(LinkStack &top) {
    LinkStack p;
    while (top) {
        p = top;
        top = top->next;
        delete p;
    }
    return OK;
}

// 清空链栈
void ClearStack_L(LinkStack top) {
    LinkStack p, q;
    p = top->next;
    while (p) {
        q = p->next;
        delete p;
        p = q;
    }
    top->next = NULL; // 头结点指针域为空,表示空栈
}

// 判断链栈是否为空
int StackEmpty_L(LinkStack top) {
    return (top->next == NULL);
}

// 入栈操作
int Push_L(LinkStack top, SElemType e) {
    LinkStack q = new STackNode;
    if (!q) return ERROR; // 内存分配失败
    q->data = e;
    q->next = top->next;
    top->next = q;
    return OK;
}

// 出栈操作
int Pop_L(LinkStack top, SElemType &e) {
    LinkStack p;
    if (StackEmpty_L(top)) return ERROR; // 栈空,返回 ERROR
    p = top->next; // p指向栈顶元素
    e = p->data; // 栈顶元素值存入e中
    top->next = p->next; // 将p所指结点从栈中删除,即出栈操作
    delete p; // 释放p所指结点占用的空间
    return OK;
}

// 取栈顶元素
int GetTop_L(LinkStack top, SElemType &e) {
    LinkStack p;
    if (StackEmpty_L(top)) return ERROR; // 栈空,返回 ERROR
    p = top->next; // p指向栈顶元素
    e = p->data; // 栈顶元素值存入e中
    return OK;
}

// 输出链栈
void DispStack_L(LinkStack top) {
    LinkStack p = top->next;
    if (StackEmpty_L(top)) {
        printf("栈空\n");
    } else {
        printf("栈元素为:");
        while (p) {
            printf("%c ", p->data);
            p = p->next;
        }
        printf("\n");
    }
}

// 显示菜单
void showmenu() {
    printf("\n\n\n");
    printf("*        --链栈基本运算演示--          *\n");
    printf("****************************************\n");
    printf("*       1-------链栈的初始化           *\n");
    printf("*       2-------销毁链栈               *\n");
    printf("*       3-------清空链栈               *\n");
    printf("*       4-------判断链栈是否为空       *\n");
    printf("*       5-------入栈操作               *\n");
	printf("*       6-------出栈操作               *\n");
	printf("*       7-------取栈顶元素             *\n");
	printf("*                                      *\n");
    printf("*       0-------退出                   *\n");
    printf("****************************************\n");
}

void Stack_L() {
    char choice = 'N';
    SElemType item;
    
    LinkStack top; //定义栈顶指针;
    int flag = 0; //是否创建好了链栈
    
    while (choice != '0') {
    	printf("\n请选择菜单号(0--7):"); 
        scanf(" %c", &choice);
        
        switch (choice) {
            case '1':
                printf("初始化链栈操作\n");
                if (InitStack_L(top)){
                    printf("初始化成功!\n");
                    flag = 1; //标志链栈的存在
                } else
                    printf("初始化失败!\n");
                break;
            case '2':
                if (flag) { //链栈存在
                    DestroyStack_L(top);
                    flag = 0; //链栈已删除
                    printf("链栈删除成功!\n");
                } else {
                    printf("链栈不存在,操作失败!\n");
                }
                break;
			case '3':
           		if (flag) { //链栈存在
                    ClearStack_L(top);
                    printf("链栈清空成功!\n");
                    DispStack_L(top);
                } else {
                    printf("链栈不存在,操作失败!\n");
                }
                break;
                
            case '4':
			    if (flag) { //链栈存在
			        printf("链栈%s\n", StackEmpty_L(top) ? "空" : "不空");
			        DispStack_L(top); //输出线性表
			    } else {
			        printf("链栈不存在,操作失败!\n");
			    }
			    break;
			
			case '5':
			    if (flag) { //链栈存在
			        printf("请输入要入栈的元素的值:");
			        scanf(" %c", &item);
			        Push_L(top, item);
			        printf("该元素已入栈\n");
			        DispStack_L(top); //输出线性表
			    } else {
			        printf("链栈不存在,操作失败!\n");
			    }
			    break;
			
			case '6':
			    if (flag) { //链栈存在
			        if (Pop_L(top, item))
			            printf("出栈元素为:%c\n", item);
			        else
			            printf("栈空!\n");
			        DispStack_L(top); //输出线性表
			    } else {
			        printf("链栈不存在,操作失败!\n");
			    }
			    break;
			
			case '7':
			    if (flag) { //链栈存在
			        if (GetTop_L(top, item))
			            printf("栈顶元素为:%c\n", item);
			        else
			            printf("栈空!\n");
			        DispStack_L(top); //输出线性表
			    } else {
			        printf("链栈不存在,操作失败!\n");
			    }
			    break;
			
			case '0':
			    printf("\n\t程序结束!\n");
			    DestroyStack_L(top);
			    break;
			
			default:
			    printf("\n\t选择错误,请重新输入!\n");
			    break;
        }
    }
}


int main() {
	showmenu();
    Stack_L();
    return 0;
}

4.运行结果:
在这里插入图片描述在这里插入图片描述

5.调试:
栈空测试:
尝试从空栈中弹出元素,验证程序是否能够正确检测到栈空并输出相应的提示信息。
预期结果:程序应提示“栈空”并阻止弹出操作。


总结

(1)顺序栈:
顺序栈实现简单,但需要预先定义栈的最大容量。
在栈满时,需要扩展栈的容量,可能导致性能下降。
(2)链栈:
链栈实现灵活,不需要预先定义栈的最大容量。
内存分配和释放需要注意,避免内存泄漏。
(3)实验收获:
通过本次实验,加深了对栈的理解和掌握。
学会了如何设计和实现栈的基本操作,并进行调试和测试。
认识到不同实现方式的优缺点,以及在实际应用中如何选择合适的实现方式。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【IEEE Fellow 主讲报告| EI检索稳定】第五届机器学习与智能系统工程国际学术会议(MLISE 2025)

重要信息 会议时间地点&#xff1a;2025年6月13-15日 中国深圳 会议官网&#xff1a;http://mlise.org EI Compendex/Scopus稳定检索 会议简介 第五届机器学习与智能系统工程国际学术会议将于6月13-15日在中国深圳隆重召开。本次会议旨在搭建一个顶尖的学术交流平台&#xf…

一文详解Filter类源码和应用

背景 在日常开发中&#xff0c;经常会有需要统一对请求做一些处理&#xff0c;常见的比如记录日志、权限安全控制、响应处理等。此时&#xff0c;ServletApi中的Filter类&#xff0c;就可以很方便的实现上述效果。 Filter类 是一个接口&#xff0c;属于 Java Servlet API 的一部…

开发环境搭建-1:配置 WSL (类 centos 的 oracle linux 官方镜像)

一些 Linux 基本概念 个人理解&#xff0c;并且为了便于理解&#xff0c;可能会存在一些问题&#xff0c;如果有根本上的错误希望大家及时指出 发行版 WSL 的系统是基于特定发行版的特定版本的 Linux 发行版 有固定组织维护的、开箱就能用的 Linux 发行版由固定的团队、社区…

llama-2-7b权重文件转hf格式及模型使用

目录 1. obtain llama weights 2. convert llama weights files into hf format 3. use llama2 to generate text 1. obtain llama weights &#xff08;1&#xff09;登录huggingface官网&#xff0c;搜索llama-2-7b &#xff08;2&#xff09;填写申请表单&#xff0c;VP…

ElasticSearch(十一)— Elasticsearch中的SQL语句

一、总概 Elasticsearch 在 Basic 授权中支持以 SQL 语句的形式检索文档&#xff0c;SQL 语句在执行时会被翻译为 DSL 执行。从语法的角度来看&#xff0c;Elastisearch 中的 SQL 语句与RDBMS 中的 SQL 语句基本一致&#xff0c; 所以对于有数据库编程基础的人来说大大降低了使…

吴恩达深度学习——如何实现神经网络

来自吴恩达深度学习&#xff0c;仅为本人学习所用。 文章目录 神经网络的表示计算神经网络的输出激活函数tanh选择激活函数为什么需要非激活函数双层神经网络的梯度下降法 随机初始化 神经网络的表示 对于简单的Logistic回归&#xff0c;使用如下的计算图。 如果是多个神经元…

爬取NBA球员信息并可视化小白入门

网址:虎扑体育-NBA球员得分数据排行 第1页 步骤: 分析页面 确定URL地址模拟浏览器向服务器发送请求数据解析 提取想要的数据保存数据 爬虫所需要的模块 requests(发送HTTP请求)parsel(解析HTML内容)pandas(数据保存模块) 第一步分析页面 --确定是静态页面还是动态页面 右击点…

C语言初阶牛客网刷题——JZ17 打印从1到最大的n位数【难度:入门】

1.题目描述 牛客网OJ题链接 题目描述&#xff1a; 输入数字 n&#xff0c;按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3&#xff0c;则打印出 1、2、3 一直到最大的 3 位数 999。 用返回一个整数列表来代替打印n 为正整数&#xff0c;0 < n < 5 示例1 输入&…

寒假刷题记录

4968. 互质数的个数 - AcWing题库 涉及&#xff1a;快速幂&#xff0c;欧拉函数&#xff0c;分解质因数 #include <bits/stdc.h> #define fi first #define se second #define endl \n #define pb push_backusing namespace std; using LL long long;const int mod 9…

OSI5GWIFI自组网协议层次对比

目录 5G网络5G与其他协议栈各层映射 5G网络 物理层 (PHY) 是 5G 基站协议架构的最底层&#xff0c;负责将数字数据转换为适合无线传输的信号&#xff0c;并将接收到的无线信号转换为数字数据。实现数据的编码、调制、多天线处理、资源映射等操作。涉及使用新的频段&#xff08…

Java高频面试之SE-16

hello啊&#xff0c;各位观众姥爷们&#xff01;&#xff01;&#xff01;本牛马baby今天又来了&#xff01;哈哈哈哈哈嗝&#x1f436; Java中异常的处理方式有哪些&#xff1f; 在 Java 中&#xff0c;异常的处理方式主要有以下几种&#xff1a; 1. 使用 try-catch 语句 …

HTML中的`<!DOCTYPE html>`是什么意思?

诸神缄默不语-个人CSDN博文目录 在学习HTML时&#xff0c;我们经常会看到HTML文档的开头出现<!DOCTYPE html>&#xff0c;它是HTML文件的第一行。很多初学者可能会疑惑&#xff0c;为什么需要这行代码&#xff1f;它到底有什么作用呢&#xff1f;在这篇文章中&#xff0…

Games104——游戏中地形大气和云的渲染

原文链接 原文链接 这里写目录标题 地形的几何Heightfield高程图网格自适应细分三角形的剖分二叉树T-Junctions四叉树TIN&#xff08;Triangulated Irregular Network&#xff09;不规则三角形网格 GPU Drived Tessellator(Hardware Tessellation)Mesh ShaderNon-HeightField…

Springboot自动配置的原理

先拿redis来举个例子 第一步导入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> 第二步配置 spring: redis: database:host:127.0.0.1 port…

【动态规划】落花人独立,微雨燕双飞 - 8. 01背包问题

本篇博客给大家带来的是01背包问题之动态规划解法技巧. &#x1f40e;文章专栏: 动态规划 &#x1f680;若有问题 评论区见 ❤ 欢迎大家点赞 评论 收藏 分享 如果你不知道分享给谁,那就分享给薯条. 你们的支持是我不断创作的动力 . 王子,公主请阅&#x1f680; 要开心要快乐顺便…

记一次虚机上传过慢问题排查

最近线上虚机有个特殊的用户反馈&#xff0c;用户反馈虚机从A服务器下载文件特别慢&#xff0c;于是scp A服务器数据到本地client&#xff0c;发现 只有几十K的流量。 当时第一反应怀疑是虚机负载压力比较大&#xff0c;但是查看虚机IO以及负载都很低。。。。 然后tcpdump抓包发…

web服务器 网站部署的架构

WEB服务器工作原理 Web web是WWW(World Wide Web)的简称&#xff0c;基本原理是&#xff1a;请求(客户端)与响应(服务器端)原理&#xff0c;由遍布在互联网中的Web服务器和安装了Web浏览器的计算机组成 客户端发出请求的方式&#xff1a;地址栏请求、超链接请求、表单请求 …

数据结构——实验七·排序

嗨~~欢迎来到Tubishu的博客&#x1f338;如果你也是一名在校大学生&#xff0c;正在寻找各种编程资源&#xff0c;那么你就来对地方啦&#x1f31f; Tubishu是一名计算机本科生&#xff0c;会不定期整理和分享学习中的优质资源&#xff0c;希望能为你的编程之路添砖加瓦⭐&…

Windows系统提示RunDLL PcaWallpaperAppDetect错误修复方法

最近&#xff0c;Win11 24H2预览版和Win10 LTSC 2025功能更新偶尔会触发RunDLL错误弹窗 具体表现为 //英文提示 Error in C:\WINDOWS\system32\PcaSvc.dll Missing entry: PcaWallpaperAppDetect//中文提示 C:\WINDOWS\system32\PcaSvc.dll出错 丢失条目:PcaWallpaperAppDe…

计算机组成原理——数据表示(二)

当生活的压力和困惑缠绕在身边&#xff0c;我们往往需要振奋精神&#xff0c;勇往直前。无论在何种困境中&#xff0c;我们都要保持积极的态度和坚定的信念。将悲观的情绪抛之脑后&#xff0c;展现出坚强的意志力和无尽的活力。振奋精神意味着我们要战胜自己内心的负面情绪&…