C++11 数据结构6 栈的链式存储,实现,测试

栈顶放在链表的头部

栈顶放在链表的头部还是尾部呢?

需要栈 是特殊的线性表,那么我们回忆一下 线性表的链式存储的插入和删除的写法,就应该能理清线性表的头部做为栈顶 合适  还是 线性表的尾部 作为栈顶合适

插入算法 核心代码

	//正式插入数据,int i = 0;LinkListNode *curSeqListNode = &(tempseqlist->head);//让curSeqListNode 指向 链表的头部for (int i = 0; i < pos; ++i) {curSeqListNode = curSeqListNode->next;}node->next = curSeqListNode->next;curSeqListNode->next = node;tempseqlist->length++;return ret;

删除算法 核心代码

	//辅助指针变量curSeqListNode,指向的位置是链表的头部LinkListNode *curSeqListNode = &(tempseqlist->head);//让curSeqListNode 指向 链表的头部int i = 0;for (i = 0; i < pos; ++i) {curSeqListNode = curSeqListNode->next;}retSeqListNode = curSeqListNode->next;	//先将要删除的节点缓存出来curSeqListNode->next = retSeqListNode->next;// 删除的节点的next中保存着 “要删除元素的下一个元素”,让curseqlistnode->next 指向tempseqlist->length--;return retSeqListNode;

从这两个算法都能看出,如果要在pos 位置插入元素 或者 删除元素,那么先要遍历到pos 位置,因此我们在 线性表的头部 做为 栈顶 比较合理。因此不管是插入元素,或者是删除元素,都是对线性表的头部的第一个元素进行处理。

相关代码:

#ifndef __006LINKSTACK_H__
#define __006LINKSTACK_H__typedef void LinkStack; //链表的返回值,需要使用void *typedef struct LinkStackNode {  //链表节点struct LinkStackNode *next;
}LinkStackNode;// 初始化,建立一个空的链表 
//返回值不为NULL,表示创建成功。
//返回值为NULL,表示创建失败。
LinkStack* LinkStack_Create();//销毁该线性表
//返回值为1,表示成功。
//返回值为-1,表示失败。
int LinkStack_Destory(LinkStack *list);//清空seqlist
//返回值为1,表示成功。
//返回值为-1,表示失败。
int LinkStack_Clear(LinkStack *list);// 返回线性表List存在的元素个数
//返回值 >=0 表示:该list存在的元素个数
//<0 表示error
int LinkStack_Length(LinkStack *list);//从LinkStack 中获取栈顶位置的数据,实际上是 栈的第一个链表的数据
//返回值:为存储在该位置的元素
//返回NULL 表示有问题
LinkStackNode* LinkStack_Get(LinkStack *list);//给LinkStack中指定位置插入数据,
//参数LinkStackNode为要插入的数据
//参数 pos 为要插入的位置
//成功返回1
//失败 返回<0int LinkStack_Insert(LinkStack *list, LinkStackNode *node);//从LinkStack 中删除栈顶位置的元素,实际上删除的链表的除了头结点的第一个元素
//参数 pos
//返回值为 删除的元素
//返回NULL 表示出现了error
LinkStackNode* LinkStack_Delete(LinkStack *list);//判断当前linkstack 是否为null,如果为null,则返回1
//如果不为NULL,则返回-1;
int isEmptyLinkStack(LinkStack *list);
#endif

#include "006linkstack.h"
#include "stdlib.h"
#include "stdio.h"
#include "string.h"typedef struct LinkStack {LinkStackNode head;int length;// 该链表的大小
}TLinkStack;// 初始化,建立一个空的链表 
//返回值不为NULL,表示创建成功。
//返回值为NULL,表示创建失败。
LinkStack* LinkStack_Create() {TLinkStack * ts = (TLinkStack *)malloc(sizeof(TLinkStack));if (ts == NULL) {printf("LinkStack_Create error list==NULL\n");return NULL;}memset(ts, 0, sizeof(TLinkStack));ts->head.next = NULL;ts->length = 0;return ts;
}//销毁该线性表
//返回值为1,表示成功。
//返回值为-1,表示失败。
int LinkStack_Destory(LinkStack *list) {int ret = 1;if (list ==NULL) {ret = -1;printf("func LinkStack_Destory error bacesue list = NULL return ret = -1\n");return ret;}TLinkStack * ts = list;free(ts);ts = NULL;list = NULL;return ret;
}//清空seqlist
//返回值为1,表示成功。
//返回值为-1,表示失败。
int LinkStack_Clear(LinkStack *list) {int ret = 1;if (list == NULL) {ret = -1;printf("func LinkStack_Clear error bacesue list = NULL return ret = -1\n");return ret;}TLinkStack * ts = list;ts->head.next = NULL;ts->length = 0;return ret;
}// 返回线性表List存在的元素个数
//返回值 >=0 表示:该list存在的元素个数
//<0 表示error
int LinkStack_Length(LinkStack *list) {int ret = 0;if (list == NULL) {ret = -1;printf("func LinkStack_Length error bacesue list = NULL return ret = -1\n");return ret;}TLinkStack * ts = list;return ts->length;
}//从LinkStack 中获取指定位置的数据
//参数pos:LinkStack中的位置
//返回值:为存储在该位置的元素
//返回NULL 表示有问题
LinkStackNode* LinkStack_Get(LinkStack *list) {LinkStackNode* ret = NULL;if (list == NULL) {ret = NULL;printf("func LinkStack_Get error bacesue list = NULL return ret = NULL\n");return ret;}TLinkStack * ts = list;if (ts->length==0) {ret = NULL;printf("func LinkStack_Get error bacesue ts->length = 0 return ret = NULL\n");return ret;}return ts->head.next;
}//给LinkStack中指定位置插入数据,
//参数LinkStackNode为要插入的数据
//参数 pos 为要插入的位置
//成功返回1
//失败 返回<0int LinkStack_Insert(LinkStack *list, LinkStackNode *node) {int ret = 1;if (list == NULL) {ret = -1;printf("func LinkStack_Insert error bacesue list = NULL return ret = -1\n");return ret;}TLinkStack * ts = list;node->next = ts->head.next;ts->head.next = node;ts->length++;return ret;
}//从LinkList 中删除指定位置的元素
//参数 pos
//返回值为 删除的元素
//返回NULL 表示出现了error
LinkStackNode* LinkStack_Delete(LinkStack *list) {LinkStackNode* ret = NULL;if (list == NULL) {ret = NULL;printf("func LinkStack_Delete error bacesue list = NULL return ret = NULL\n");return ret;}TLinkStack * ts = list;if (ts->length == 0) {ret = NULL;printf("func LinkStack_Delete error bacesue ts->length = 0 return ret = NULL\n");return ret;}LinkStackNode * delnode = ts->head.next;ts->head.next = delnode->next;ts->length--;return delnode;}//判断当前linkstack 是否为null,如果为null,则返回1
//如果不为NULL,则返回0;
//有error 则返回-1
int isEmptyLinkStack(LinkStack *list) {int ret = 0;if (list == NULL) {ret = -1;printf("func isEmptyLinkStack error bacesue list = NULL return ret = -1\n");return ret;}TLinkStack * ts = list;int length = ts->length;if (length>0) {ret = 0;}else {ret = 1;}return ret;
}

#define _CRT_SECURE_NO_WARNINGS
#define _CRTDBG_MAP_ALLOC
#include "iostream"
#include <stdio.h>
#include <stdlib.h>extern "C" {
#include "006linkstack.h"
}typedef struct Teacher {LinkStackNode  linkstacknode;int age;char name[128];char *othername;char **stuname; //一个老师下面有5个学生
}Teacher;int main() {_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);//程序退出时检测内存泄漏并显示到“输出”窗口int ret = 0;//初始化队列,要动态的创建SeqStack,根据user设定的大小创建
//int stacksize ,表示user 要创建栈的大小
//创建失败返回NULLLinkStack* linkstack = LinkStack_Create();if (linkstack == NULL) {ret = -1;printf("func LinkStack_Create error because linkstack = NULL return ret =-1\n");return ret;}ret = isEmptyLinkStack(linkstack);printf("isEmptyLinkStack = ret %d\n", ret);ret = LinkStack_Length(linkstack);printf("LinkStack_Length = ret %d\n", ret);Teacher tea1;tea1.age = 20;strcpy(tea1.name, (const char*)"tea1");tea1.othername = (char *)malloc(sizeof(char) * 128);memset(tea1.othername, 0, sizeof(char) * 128);strcpy(tea1.othername, (const char*)"tea1othername");tea1.stuname = (char **)malloc(sizeof(char *) * 5);memset(tea1.stuname, 0, sizeof(char *) * 5);for (size_t i = 0; i < 5; i++){tea1.stuname[i] = (char *)malloc(sizeof(char) * 128);//每个学生名字也有128个字符memset(tea1.stuname[i], 0, sizeof(char) * 128);sprintf(tea1.stuname[i], "tea1stuname%d", i + 1);}Teacher tea2;tea2.age = 22;strcpy(tea2.name, (const char*)"tea2");tea2.othername = (char *)malloc(sizeof(char) * 128);memset(tea2.othername, 0, sizeof(char) * 128);strcpy(tea2.othername, (const char*)"tea2othername");tea2.stuname = (char **)malloc(sizeof(char *) * 5);memset(tea2.stuname, 0, sizeof(char *) * 5);for (size_t i = 0; i < 5; i++){tea2.stuname[i] = (char *)malloc(sizeof(char) * 128);//每个学生名字也有128个字符memset(tea2.stuname[i], 0, sizeof(char) * 128);sprintf(tea2.stuname[i], "tea2stuname%d", i + 1);}Teacher tea3;tea3.age = 33;strcpy(tea3.name, (const char*)"tea3");tea3.othername = (char *)malloc(sizeof(char) * 128);memset(tea3.othername, 0, sizeof(char) * 128);strcpy(tea3.othername, (const char*)"tea3othername");tea3.stuname = (char **)malloc(sizeof(char *) * 5);memset(tea3.stuname, 0, sizeof(char *) * 5);for (size_t i = 0; i < 5; i++){tea3.stuname[i] = (char *)malloc(sizeof(char) * 128);//每个学生名字也有128个字符memset(tea3.stuname[i], 0, sizeof(char) * 128);sprintf(tea3.stuname[i], "tea3stuname%d", i + 1);}ret = LinkStack_Insert(linkstack, (LinkStackNode * )&tea1);if (ret < 0) {printf("LinkStack_Insert(linkstack, (LinkStackNode * )&tea1) func error ret =%d \n", ret);return ret;}ret = LinkStack_Insert(linkstack, (LinkStackNode *)&tea2);if (ret < 0) {printf("LinkStack_Insert(linkstack, (LinkStackNode * )&tea2) func error ret =%d \n", ret);return ret;}ret = LinkStack_Insert(linkstack, (LinkStackNode *)&tea3);if (ret < 0) {printf("LinkStack_Insert(linkstack, (LinkStackNode * )&tea3) func error ret =%d \n", ret);return ret;}printf("-after-\n");ret = isEmptyLinkStack(linkstack);printf("isEmptyLinkStack = ret %d\n", ret);ret = LinkStack_Length(linkstack);printf("LinkStack_Length = ret %d\n", ret);while (LinkStack_Length(linkstack) > 0) {Teacher * temptea = (Teacher *)LinkStack_Get(linkstack);if (temptea == NULL) {printf("can not get find teacher\n");}printf("temptea->age = %d,temptea->name = %s,temptea->othername=%s\n",temptea->age,temptea->name,temptea->othername);for (size_t j = 0; j < 5; j++){printf("temptea->stuname[%d] = %s,  ",j, temptea->stuname[j]);}Teacher * deltea = (Teacher *)LinkStack_Delete(linkstack);if (deltea == NULL) {printf("LinkStack_Delete seqstack error\n");}if (deltea->othername != NULL) {free(deltea->othername);}if (deltea->stuname != NULL) {for (size_t i = 0; i < 5; i++){if (deltea->stuname[i] != NULL) {free(deltea->stuname[i]);}}free(deltea->stuname);deltea->stuname = NULL;}printf("\n");}printf("sss\n");//销毁栈//成功 返回1 表示成功销毁栈 //失败 返回-1 表示该函数执行的时候有问题ret = LinkStack_Destory(linkstack);return 0;}

相关应用:实现编译器中的符号成对检测

//几乎所有的编译器都具有检测括号是否匹配的能力,
//那么如何实现编译器中的符号成对检测?如下字符串:
//5 + 5 * (6) + 9 / 3 * 1) - (1 + 3(
//算法思路
//
//从第一个字符开始扫描
//当遇见普通字符时忽略,
//当遇见左括号时压入栈中
//当遇见右括号时从栈中弹出栈顶符号,并进行匹配
//匹配成功:继续读入下一个字符
//匹配失败:立即停止,并报错
//结束:
//成功 : 所有字符扫描完毕,且栈为空
//    失败:匹配失败或所有字符扫描完毕但栈非空

//总结:
//当需要检测成对出现但又互不相邻的事物时可以使用栈“后进先出”的特性

#define _CRT_SECURE_NO_WARNINGS
#define _CRTDBG_MAP_ALLOC
#include "iostream"
#include <stdio.h>
#include <stdlib.h>//几乎所有的编译器都具有检测括号是否匹配的能力,
//那么如何实现编译器中的符号成对检测?如下字符串:
//5 + 5 * (6) + 9 / 3 * 1) - (1 + 3(
//算法思路
//
//从第一个字符开始扫描
//当遇见普通字符时忽略,
//当遇见左括号时压入栈中
//当遇见右括号时从栈中弹出栈顶符号,并进行匹配
//匹配成功:继续读入下一个字符
//匹配失败:立即停止,并报错
//结束:
//成功 : 所有字符扫描完毕,且栈为空
//	失败:匹配失败或所有字符扫描完毕但栈非空//总结:
//当需要检测成对出现但又互不相邻的事物时可以使用栈“后进先出”的特性char *err1 = (char *)"无法找到对应的右括号的 左括号";
char *err2 = (char *)"该 左括号 没有对应的有括号";extern "C" {
#include "004seqstack.h"
}int isLeft( char ch) {if ('(' == ch) {return 1;}return 0;
}int isRight(char ch) {if (')' == ch) {return 1;}return 0;
}void printerror(char* err,char *str, char *ptemp) {printf("err start");printf(err);printf("原始字符串如下\n");printf(str);printf("\n");printf("error位置如下\n");int num = ptemp - str;while (num > 0 ) {printf(" ");--num;}printf("|\n");printf("err end");
}void testchar(char *str) {SeqStack * seqstack = createSeqStack(1024);if (seqstack ==NULL) {printf("func testchar error because seqstack==NULL\n");return;}if (str == NULL) {printf("testchar func error because str==NULL\n");return;}char *ptemp = str;//让辅助指针变量指向传递过来的strwhile (*(ptemp) != '\0') {if (isLeft(*ptemp)) { 当遇见左括号时压入栈中.判断是否是符号,如果是 左括号 符号,则要进栈,push_SeqStack(seqstack,ptemp);}if (isRight(*ptemp)) {//当遇见右括号时从栈中弹出栈顶符号,并进行匹配//如果这时候栈中啥也没有,就有问题,直接break;if (size_SeqStack(seqstack) == 0) {printerror(err1,str,ptemp);break;}pop_SeqStack(seqstack);}ptemp++;}//当将整个字符串都弄完成后,检查栈中是否有元素,如果栈中有元素,说明有左括号没有匹配while (size_SeqStack(seqstack) > 0 ) {printerror(err2, str, (char *)top_SeqStack(seqstack));pop_SeqStack(seqstack);}
}int main() {int ret = 0;_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);//程序退出时检测内存泄漏并显示到“输出”窗口//char* sourcestr = (char *)"5 + 5 * (6) + 9 / 3 * 1) - (1 + 3(";char* sourcestr = (char *)"5 + 5 * (6) + 9 / 3 * 1 - (1 + 3(";testchar(sourcestr);return ret;
}

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

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

相关文章

深度学习| 注意力机制

注意力机制 为什么需要注意力机制Seq2Seq问题Transfomer Attention注意力机制分类软硬注意力注意力域 为什么需要注意力机制 这个可以从NLP的Seq2Seq问题来慢慢理解。 Seq2Seq问题 Seq2Seq&#xff08;Sequence to Sequence&#xff09;&#xff1a;早期很多模型中&#xff…

数据赋能(67)——概念:数据变现

数据变现是指通过某种方式将数据转化为实际的收益或绩效。数据变现的方式多种多样&#xff0c;可以根据不同的应用场景和业务需求进行选择和组合。 数据变现的主要方式如下&#xff1a; 数据销售与租赁 组织直接出售原始数据或经过处理、整合后的数据给需要的组织或个人。组织…

Redis分布式锁 - 基于Jedis和LUA的分布式锁

先基于单机模式&#xff0c;基于Jedis手工造轮子实现自己的分布式锁。 首先看两个命令&#xff1a; Redis 分布式锁机制&#xff0c;主要借助 setnx 和 expire 两个命令完成。 setnx命令: setnx 是 set if not exists 的简写。将 key 的值设为 value &#xff0c;当且仅当…

uniapp问题归类

最近使用uniapp中&#xff0c;遇到了一些问题&#xff0c;这边mark下。 1. 启动页变形 设置启动页的时候发现在部分android手机上启动页被拉伸了&#xff0c;最后看了下官方建议使用9.png图 生成9.png地址&#xff0c;推荐图片大小为1080x2340 uniapp推荐官方地址传送门 我…

【Linux驱动层】iTOP-RK3568学习之路(四):杂项设备驱动框架

一、杂项设备驱动简介 在 Linux 中&#xff0c;把无法归类的五花八门的设备定义成杂项设备。相较于字符设备&#xff0c;杂项设备有以下两个优点: (1)节省主设备号:杂项设备的主设备号固定为 10&#xff0c;而字符设备不管是动态分配还是静态分配设备号&#xff0c;都会消耗一…

【leetcode面试经典150题】71. 对称二叉树(C++)

【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主&#xff0c;题解使用C语言。&#xff08;若有使用其他语言的同学也可了解题解思路&#xff0c;本质上语法内容一致&…

Golang | Leetcode Golang题解之第48题旋转图像

题目&#xff1a; 题解&#xff1a; func rotate(matrix [][]int) {n : len(matrix)// 水平翻转for i : 0; i < n/2; i {matrix[i], matrix[n-1-i] matrix[n-1-i], matrix[i]}// 主对角线翻转for i : 0; i < n; i {for j : 0; j < i; j {matrix[i][j], matrix[j][i]…

Nuxt3项目如何通过开启ssr让网页实现seo自由!

nuxt.config开启ssr # nuxt.config.tsexport default defineNuxtConfig({// 是否开启SSRssr: true }) 终端运行 npm run generate generate 预渲染应用程序的每个路由&#xff0c;并将结果存储为纯HTML文件。 "scripts": {"generate": "nuxt genera…

【Git教程】(十七)发行版交付 — 概述及使用要求,执行过程及其实现,替代解决方案 ~

Git教程 发行版交付 1️⃣ 概述2️⃣ 使用要求3️⃣ 执行过程及其实现3.1 预备阶段&#xff1a;创建 stable 分支3.2 预备并创建发行版3.3 创建补丁 4️⃣ 替代解决方案 对于每个项目或产品来说&#xff0c;发布版本的创建都需要一定的时间&#xff0c;其具体过程因各公司或组…

C++ Qt QMainWindow实现无边框窗口自定义标题栏可拖拽移动拉伸改变窗口大小

本篇博客介绍C Qt QMainWindow实现无边框窗口&#xff0c;适用于win10/win11系统。 QMainWindow相对于QWidget多了dockedwidget功能&#xff0c;跟多人可能更喜欢用QMainWindow做主窗口&#xff0c;如果不需要dockedwidget功能&#xff0c;QMainWindow与QWidget做主窗口基本无…

MATLAB实现蚁群算法栅格路径优化

蚁群算法是一种模拟自然界中蚂蚁觅食行为的优化算法&#xff0c;常用于解决路径规划问题。在栅格路径优化中&#xff0c;蚁群算法可以帮助找到从起点到终点的最优路径。以下是蚁群算法栅格路径优化的基本流程步骤&#xff1a; 初始化参数&#xff1a; (1)设置蚂蚁数量&#xff…

linux的“>”和“>>”

在Linux中&#xff0c;>和>>都是用于文件重定向的操作符&#xff0c;它们用于将命令的输出发送到文件中。 > 用于创建一个新文件或覆盖现有文件的内容。当你执行一个如 command > file.txt 的命令时&#xff0c;如果 file.txt 文件存在&#xff0c;它的内容将被…

2024最新版JavaScript逆向爬虫教程-------基础篇之深入JavaScript运行原理以及内存管理

目录 一、JavaScript运行原理1.1 前端需要掌握的三大技术1.2 为什么要学习JavaScript1.3 浏览器的工作原理1.4 浏览器的内核1.5 浏览器渲染过程1.6 认识JavaScript引擎1.7 V8引擎以及JavaScript的执行过程1.8 V8引擎执行过程 二、JavaScript的执行过程2.1 初始化全局对象2.2 执…

OriginPro作图之箱线图

前言 箱线图(Box-plot) 又称为盒须图、盒式图或箱线图&#xff0c;是一种用作显示一组数据分散情况资料的统计图。因型状如箱子而得名。 本文将结合实例阐述其意义和绘图过程。 箱线图简介 箱线图(Boxplot) 也称箱须图( Box-whisker Plot)&#xff0c;是利用数据中的五个统计量…

ffmpeg的安装以及使用

1.FFmpeg 的主要功能和特性&#xff1a; 格式转换&#xff1a;FFmpeg 可以将一个媒体文件从一种格式转换为另一种格式&#xff0c;支持几乎所有常见的音频和视频格式&#xff0c;包括 MP4、AVI、MKV、MOV、FLV、MP3、AAC 等。视频处理&#xff1a;FFmpeg 可以进行视频编码、解…

ArcGIS无法开始编辑TIN!开始编辑TIN显示灰色

ArcGIS无法开始编辑TIN&#xff01;开始编辑TIN显示灰色&#xff1f; 解决方案&#xff01; 1、确认自定义——扩展模块中空间分析、3D分析模块勾选。 2、确认以上后&#xff0c;还是不能编辑的话&#xff0c;我们可以调出 3D分析分析工具条&#xff0c;你就会发现。TIN编辑工…

Window + Ubuntu 双系统无Ubuntu Bios 启动项

文章目录 安装硬盘位置不重要&#xff01;&#xff01;&#xff01;&#xff08;但是我安装在了第二张HDD&#xff09;问题是多盘分位置会导致磁盘主分区变成了简单卷 Bios Ubuntu 启动项修复参考Ubuntu安装U盘进入Try Ubuntu 使用Terminal修复完提示Disable Secure Boot进入Te…

【存储】cosbench对象存储测试工具

目录 简略说明 原理 用法 详细说明 简介 用法 一 安装 二 简单验证 三 编写配置文件 四 提交配置文件下IO 五 测试结果查看 结果概览 查看详情 每秒钟的io情况查看 工作负载配置 参数配置&#xff08;controller和driver&#xff09; 查看错误的方法和错误记录 查看错误的方法 …

【匹配】匈牙利匹配算法

every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 匈牙利匹配算法 1. 正文 1.1 基础概念 二分图 顶点分为两个集合&#xff0c;集合间顶点相连&#xff0c;集合内点不相连 匹配 一个匹配就是一个边的…

Oracle Linux 8.8 一键安装 Oracle 11GR2 RAC(231017)

前言 Oracle 一键安装脚本&#xff0c;演示 Oracle Linux 8.8 一键安装 Oracle 11GR2 RAC&#xff08;231017&#xff09;过程&#xff08;全程无需人工干预&#xff09;&#xff1a;&#xff08;脚本包括 ORALCE PSU/OJVM 等补丁自动安装&#xff09; ⭐️ 脚本下载地址&…