编程题-栈,链栈

概念

栈(Stack):是只允许在一端进行插入或删除的线性表。首先栈是一种线性表,但限定这种线性表只能在某一端进行插入和删除操作。 栈顶(Top):线性表允许进行插入删除的那一端。 栈底(Bottom):固定的,不允许进行插入和删除的另一端。 空栈:不含任何元素的空表。

链栈,就是使用链式结构来实现栈,链栈的空间可以是不连续分配。如果是为了省内存,这个方法比较好。

程序

一、栈的存储和访问

 #define STACK_INIT_SIZE 10 /* 存储空间初始分配量 */#define STACKINCREMENT 2 /* 存储空间分配增量 */typedef struct SqStack{SElemType *base; /* 在栈构造之前和销毁之后,base的值为NULL */SElemType *top; /* 栈顶指针 */int stacksize; /* 当前已分配的存储空间,以元素为单位 */}SqStack; /* 顺序栈 *//*  9个顺序栈的基本操作  */Status InitStack(SqStack *S){ /* 构造一个空栈S */(*S).base=(SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));if(!(*S).base)exit(OVERFLOW); /* 存储分配失败 */(*S).top=(*S).base;(*S).stacksize=STACK_INIT_SIZE;return OK;}Status DestroyStack(SqStack *S){ /* 销毁栈S,S不再存在 */free((*S).base);(*S).base=NULL;(*S).top=NULL;(*S).stacksize=0;return OK;}Status ClearStack(SqStack *S){ /* 把S置为空栈 */(*S).top=(*S).base;return OK;}Status StackEmpty(SqStack S){ /* 若栈S为空栈,则返回TRUE,否则返回FALSE */if(S.top==S.base)return TRUE;elsereturn FALSE;}int StackLength(SqStack S){ /* 返回S的元素个数,即栈的长度 */return S.top-S.base;}Status GetTop(SqStack S,SElemType *e){ /* 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR */if(S.top>S.base){*e=*(S.top-1);return OK;}elsereturn ERROR;}Status Push(SqStack *S,SElemType e){ /* 插入元素e为新的栈顶元素 */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;return OK;}Status Pop(SqStack *S,SElemType *e){ /* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */if((*S).top==(*S).base)return ERROR;*e=*--(*S).top;return OK;}Status StackTraverse(SqStack S,Status(*visit)(SElemType)){ /* 从栈底到栈顶依次对栈中每个元素调用函数visit()。 *//* 一旦visit()失败,则操作失败 */while(S.top>S.base)visit(*S.base++);printf("\n");return OK;}#include"c1.h"typedef int SElemType; /* 定义栈元素类型,此句要在c3-1.h的前面 */#include"c3-1.h"#include"bo3-1.c"Status visit(SElemType c){printf("%d ",c);return OK;}void main(){int j;SqStack s;SElemType e;if(InitStack(&s)==OK)for(j=1;j<=12;j++)Push(&s,j);printf("栈中元素依次为:");StackTraverse(s,visit);Pop(&s,&e);printf("弹出的栈顶元素 e=%d\n",e);printf("栈空否:%d(1:空 0:否)\n",StackEmpty(s));GetTop(s,&e);printf("栈顶元素 e=%d 栈的长度为%d\n",e,StackLength(s));ClearStack(&s);printf("清空栈后,栈空否:%d(1:空 0:否)\n",StackEmpty(s));DestroyStack(&s);printf("销毁栈后,s.top=%u s.base=%u s.stacksize=%d\n",s.top,s.base, s.stacksize);}

二、链栈的存储和访问

链栈是线性表和栈二合一的结构,例子里包含了线性表的所有访问,然后才是栈。

 struct LNode{ElemType data;struct LNode *next;};typedef struct LNode *LinkList; /* 另一种定义LinkList的方法 */Status InitList(LinkList *L){ /* 操作结果:构造一个空的线性表L */*L=(LinkList)malloc(sizeof(struct LNode)); /* 产生头结点,并使L指向此头结点 */if(!*L) /* 存储分配失败 */exit(OVERFLOW);(*L)->next=NULL; /* 指针域为空 */return OK;}Status DestroyList(LinkList *L){ /* 初始条件:线性表L已存在。操作结果:销毁线性表L */LinkList q;while(*L){q=(*L)->next;free(*L);*L=q;}return OK;}Status ClearList(LinkList L) /* 不改变L */{ /* 初始条件:线性表L已存在。操作结果:将L重置为空表 */LinkList p,q;p=L->next; /* p指向第一个结点 */while(p) /* 没到表尾 */{q=p->next;free(p);p=q;}L->next=NULL; /* 头结点指针域为空 */return OK;}Status ListEmpty(LinkList L){ /* 初始条件:线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */if(L->next) /* 非空 */return FALSE;elsereturn TRUE;}int ListLength(LinkList L){ /* 初始条件:线性表L已存在。操作结果:返回L中数据元素个数 */int i=0;LinkList p=L->next; /* p指向第一个结点 */while(p) /* 没到表尾 */{i++;p=p->next;}return i;}Status GetElem(LinkList L,int i,ElemType *e) /* 算法2.8 */{ /* L为带头结点的单链表的头指针。当第i个元素存在时,其值赋给e并返回OK,否则返回ERROR */int j=1; /* j为计数器 */LinkList p=L->next; /* p指向第一个结点 */while(p&&j<i) /* 顺指针向后查找,直到p指向第i个元素或p为空 */{p=p->next;j++;}if(!p||j>i) /* 第i个元素不存在 */return ERROR;*e=p->data; /* 取第i个元素 */return OK;}int LocateElem(LinkList L,ElemType e,Status(*compare)(ElemType,ElemType)){ /* 初始条件: 线性表L已存在,compare()是数据元素判定函数(满足为1,否则为0) *//* 操作结果: 返回L中第1个与e满足关系compare()的数据元素的位序。 *//*           若这样的数据元素不存在,则返回值为0 */int i=0;LinkList p=L->next;while(p){i++;if(compare(p->data,e)) /* 找到这样的数据元素 */return i;p=p->next;}return 0;}Status PriorElem(LinkList L,ElemType cur_e,ElemType *pre_e){ /* 初始条件: 线性表L已存在 *//* 操作结果: 若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱, *//*           返回OK;否则操作失败,pre_e无定义,返回INFEASIBLE */LinkList q,p=L->next; /* p指向第一个结点 */while(p->next) /* p所指结点有后继 */{q=p->next; /* q为p的后继 */if(q->data==cur_e){*pre_e=p->data;return OK;}p=q; /* p向后移 */}return INFEASIBLE;}Status NextElem(LinkList L,ElemType cur_e,ElemType *next_e){ /* 初始条件:线性表L已存在 *//* 操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继, *//*           返回OK;否则操作失败,next_e无定义,返回INFEASIBLE */LinkList p=L->next; /* p指向第一个结点 */while(p->next) /* p所指结点有后继 */{if(p->data==cur_e){*next_e=p->next->data;return OK;}p=p->next;}return INFEASIBLE;}Status ListInsert(LinkList L,int i,ElemType e) /* 算法2.9。不改变L */{ /* 在带头结点的单链线性表L中第i个位置之前插入元素e */int j=0;LinkList p=L,s;while(p&&j<i-1) /* 寻找第i-1个结点 */{p=p->next;j++;}if(!p||j>i-1) /* i小于1或者大于表长 */return ERROR;s=(LinkList)malloc(sizeof(struct LNode)); /* 生成新结点 */s->data=e; /* 插入L中 */s->next=p->next;p->next=s;return OK;}Status ListDelete(LinkList L,int i,ElemType *e) /* 算法2.10。不改变L */{ /* 在带头结点的单链线性表L中,删除第i个元素,并由e返回其值 */int j=0;LinkList p=L,q;while(p->next&&j<i-1) /* 寻找第i个结点,并令p指向其前趋 */{p=p->next;j++;}if(!p->next||j>i-1) /* 删除位置不合理 */return ERROR;q=p->next; /* 删除并释放结点 */p->next=q->next;*e=q->data;free(q);return OK;}Status ListTraverse(LinkList L,void(*vi)(ElemType))/* vi的形参类型为ElemType,与bo2-1.c中相应函数的形参类型ElemType&不同 */{ /* 初始条件:线性表L已存在 *//* 操作结果:依次对L的每个数据元素调用函数vi()。一旦vi()失败,则操作失败 */LinkList p=L->next;while(p){vi(p->data);p=p->next;}printf("\n");return OK;}void InsertAscend(LinkList L,ElemType e){ /* 初始条件:按非降序排列的线性表L已存在。操作结果:在L中按非降序插入新的数据元素e */LinkList q=L,p=L->next;while(p&&e>p->data){q=p;p=p->next;}q->next=(LinkList)malloc(sizeof(struct LNode)); /* 插在q后 */q->next->data=e;q->next->next=p;}void InsertDescend(LinkList L,ElemType e){ /* 初始条件:按非升序排列的线性表L已存在。操作结果:在L中按非升序插入新的数据元素e */LinkList q=L,p=L->next;while(p&&e<p->data){q=p;p=p->next;}q->next=(LinkList)malloc(sizeof(struct LNode)); /* 插在q后 */q->next->data=e;q->next->next=p;}Status HeadInsert(LinkList L,ElemType e){ /* 初始条件:线性表L已存在。操作结果:在L的头部插入新的数据元素e,作为链表的第一个元素 */LinkList s;s=(LinkList)malloc(sizeof(struct LNode)); /* 生成新结点 */s->data=e; /* 给结点赋值 */s->next=L->next; /* 插在表头 */L->next=s;return OK;}Status EndInsert(LinkList L,ElemType e){ /* 初始条件:线性表L已存在。操作结果:在L的尾部插入新的数据元素e,作为链表的最后一个元素 */LinkList p=L;while(p->next) /* 使p指向表尾元素 */p=p->next;p->next=(LinkList)malloc(sizeof(struct LNode)); /* 在表尾生成新结点 */p->next->data=e; /* 给新结点赋值 */p->next->next=NULL; /* 表尾 */return OK;}Status DeleteFirst(LinkList L,ElemType *e){ /* 初始条件:线性表L已存在,且有不少于1个元素 *//* 操作结果:删除L的第一个数据元素,并由e返回其值 */LinkList p=L->next;if(p){*e=p->data;L->next=p->next;free(p);return OK;}elsereturn ERROR;}Status DeleteTail(LinkList L,ElemType *e){ /* 初始条件:线性表L已存在,且有不少于1个元素 *//* 操作结果:删除L的最后一个数据元素,并用e返回其值 */LinkList p=L,q;if(!p->next) /* 链表为空 */return ERROR;while(p->next){q=p;p=p->next;}q->next=NULL; /* 新尾结点的next域设为NULL */*e=p->data;free(p);return OK;}Status DeleteElem(LinkList L,ElemType e){ /* 删除表中值为e的元素,并返回TRUE;如无此元素,则返回FALSE */LinkList p=L,q;while(p){q=p->next;if(q&&q->data==e){p->next=q->next;free(q);return TRUE;}p=q;}return FALSE;}Status ReplaceElem(LinkList L,int i,ElemType e){ /* 用e取代表L中第i个元素的值 */LinkList p=L;int j=0;while(p->next&&j<i){j++;p=p->next;}if(j==i){p->data=e;return OK;}else /* 表中不存在第i个元素 */return ERROR;}Status CreatAscend(LinkList *L,int n){ /* 按非降序建立n个元素的线性表 */int j;LinkList p,q,s;if(n<=0)return ERROR;InitList(L);printf("请输入%d个元素:\n",n);s=(LinkList)malloc(sizeof(struct LNode)); /* 第一个结点 */scanf("%d",&s->data);s->next=NULL;(*L)->next=s;for(j=1;j<n;j++){s=(LinkList)malloc(sizeof(struct LNode)); /* 其余结点 */scanf("%d",&s->data);q=*L;p=(*L)->next;while(p&&p->data<s->data) /* p没到表尾,且所指元素值小于新值 */{q=p;p=p->next; /* 指针后移 */}s->next=q->next; /* 元素插在q的后面 */q->next=s;}return OK;}Status CreatDescend(LinkList *L,int n){ /* 按非升序建立n个元素的线性表 */int j;LinkList p,q,s;if(n<=0)return ERROR;InitList(L);printf("请输入%d个元素:\n",n);s=(LinkList)malloc(sizeof(struct LNode)); /* 第一个结点 */scanf("%d",&s->data);s->next=NULL;(*L)->next=s;for(j=1;j<n;j++){s=(LinkList)malloc(sizeof(struct LNode)); /* 其余结点 */scanf("%d",&s->data);q=*L;p=(*L)->next;while(p&&p->data>s->data) /* p没到表尾,且所指元素值大于新值 */{q=p;p=p->next; /* 指针后移 */}s->next=q->next; /* 元素插在q的后面 */q->next=s;}return OK;}Status GetFirstElem(LinkList L,ElemType *e){ /* 返回表头元素的值 */LinkList p=L->next;if(!p) /* 空表 */return ERROR;else /* 非空表 */*e=p->data;return OK;}typedef SElemType ElemType; /* 栈结点类型和链表结点类型一致 */typedef LinkList LinkStack; /* LinkStack是指向栈结点的指针类型 */#define InitStack InitList /* InitStack()与InitList()作用相同,下同 */#define DestroyStack DestroyList#define ClearStack ClearList#define StackEmpty ListEmpty#define StackLength ListLength#define GetTop GetFirstElem#define Push HeadInsert#define Pop DeleteFirstStatus StackTraverse(LinkStack S,void(*visit)(SElemType)){ /* 从栈底到栈顶依次对栈中每个元素调用函数visit()。 */SElemType e;LinkStack temp,p=S;InitStack(&temp); /* 初始化temp栈 */while(p->next){GetTop(p,&e);Push(temp,e);p=p->next;}ListTraverse(temp,visit);return OK;}#include<string.h>#include<ctype.h>#include<malloc.h> /* malloc()等 */#include<limits.h> /* INT_MAX等 */#include<stdio.h> /* EOF(=^Z或F6),NULL */#include<stdlib.h> /* atoi() */#include<io.h> /* eof() */#include<math.h> /* floor(),ceil(),abs() */#include<process.h> /* exit() *//* 函数结果状态代码 */#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0#define INFEASIBLE -1typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */typedef int SElemType; /* 定义栈元素的类型 */void print(SElemType c){printf("%d ",c);}void main(){int j;LinkStack s;SElemType e;if(InitStack(&s))for(j=1;j<=5;j++)Push(s,2*j);printf("栈中的元素从栈底到栈顶依次为: ");StackTraverse(s,print);Pop(s,&e);printf("弹出的栈顶元素为%d\n",e);printf("栈空否: %d(1:空 0:否)\n",StackEmpty(s));GetTop(s,&e);printf("当前栈顶元素为%d,栈的长度为%d\n",e,StackLength(s));ClearStack(s);printf("清空栈后,栈空否: %d(1:空 0:否),栈的长度为%d\n",StackEmpty(s),StackLength(s));printf("是否销毁栈了: %d(1:是 0:否)\n",DestroyStack(&s));}

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

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

相关文章

4、linux相关基础知识

1、gcc编译过程 .c通过编译生成.o文件&#xff0c;.out目标文件进过链接生成.so库文件。 2、在C中可以使用system(("mkdir -p "path).c_str())创建目录。c_str()把string转化为c字符串&#xff0c;便于system命令识别&#xff0c;system命令会新启动一个进程来创建文…

移动硬盘有盘符打不开:深度解析与高效恢复指南

在数字化信息爆炸的今天&#xff0c;移动硬盘作为便捷的数据存储与传输工具&#xff0c;其重要性不言而喻。然而&#xff0c;当您遇到移动硬盘有盘符却无法正常打开的情况时&#xff0c;无疑会给您的工作和生活带来不小的困扰。本文将深入探讨移动硬盘有盘符打不开的原因&#…

东软“引战”国家队 通用技术“补链”大国重器

向来低调温和的东软创始人刘积仁&#xff0c;这一次抛出了“王炸”级的资产交易。 7月3日&#xff0c;《多肽链》获得一则足以引爆国内医疗设备行业的投资信息&#xff1a;被东软集团视为核心资产、掌上明珠的东软医疗&#xff0c;成功引入通用技术集团资本有限公司与中国国有…

BI佐罗,居然抄袭洗稿我的文章

必须曝光此博主不当行径。 4月2日这天发表的原创文章&#xff1a;BI报表系统建设10大坑&#xff0c;因为都是切身的实际项目经验总结&#xff0c;获得了很多人的关注。 我觉得写文章要写的是亲身、真的做过的专业的项目经验&#xff0c;而不是信口开河随口忽悠。 如果有些博…

Fancybox: 号称世界上最流行的灯箱脚本!这款“花盒“为什么与众不同?

今天要分享的是一个灯箱脚本库&#xff1a;Fancybox。最近了不起刚好用到它。这里就和大家分享下。 简介 Fancybox 是终极的 JavaScript 灯箱替代品&#xff0c;为多媒体显示中的优质用户体验设定了标准。支持图像、视频、地图、内联内容、iframe 和任何其他 HTML 内容。 此…

reverse函数讲解

reverse&#xff1a; 在C中&#xff0c;reverse 是一个标准库函数&#xff0c;用于反转指定范围内的元素顺序。该函数定义在头文件 <algorithm> 中。它的基本用法如下&#xff1a; #include <algorithm> // 包含reverse函数 #include <vector> // 使用v…

如何在SpringCloud中使用Kafka Streams实现实时数据处理

使用Kafka Streams在Spring Cloud中实现实时数据处理可以帮助我们构建可扩展、高性能的实时数据处理应用。Kafka Streams是一个基于Kafka的流处理库&#xff0c;它可以用来处理流式数据&#xff0c;进行流式计算和转换操作。 下面将介绍如何在Spring Cloud中使用Kafka Streams实…

Pytorch中nn.Sequential()函数创建网络的几种方法

1. 创作灵感 在创建大型网络的时候&#xff0c;如果使用nn.Sequential&#xff08;&#xff09;将几个有紧密联系的运算组成一个序列&#xff0c;可以使网络的结构更加清晰。 2.应用举例 为了记录nn.Sequential&#xff08;&#xff09;的用法&#xff0c;搭建以下测试网络&…

UDP怎么实现可靠传输

UDP它不属于连接型协议&#xff0c;因而具有资源消耗小&#xff0c;处理速度快的优点&#xff0c;所以通常音频、视频和普通数据在传送时使用UDP较多&#xff0c;因为它们即使偶尔丢失一两个数据包&#xff0c;也不会对接收结果产生太大影响。传输层无法保证数据的可靠传输&…

简谈设计模式之工厂模式

工厂模式是一种创建型设计模式, 旨在将对象的创建过程和使用过程分离. 这样可以在不改变客户端代码的前提下, 灵活创建不同类型的对象 工厂模式实现 简单工厂模式 简单工厂模式使用一个工厂类根据传入的参数决定创建哪种具体产品类的实例. 它不属于设计模式的23种, 但它为理…

数字电路-建立时间和保持时间详解

对于数字系统而言&#xff0c;建立时间&#xff08;setup time&#xff09;和保持时间&#xff08;hold time&#xff09;是数字电路时序的基础。数字电路系统的稳定性&#xff0c;基本取决于时序是否满足建立时间和保持时间。我自己在初学时一度很难理解清楚他们的概念&#x…

云端典藏:iCloud中个人收藏品目录的智能存储方案

云端典藏&#xff1a;iCloud中个人收藏品目录的智能存储方案 在数字化生活不断推进的今天&#xff0c;个人收藏品的管理也趋向于电子化和云端化。iCloud作为苹果公司提供的云服务&#xff0c;为个人收藏品目录的存储和管理提供了一个安全、便捷、跨设备的解决方案。本文将详细…

0145__Linux的capability

https://zhuanlan.zhihu.com/p/693896673 Linux的capability深入分析&#xff08;1&#xff09;_linux 设置进程capprm-CSDN博客 cap_init(3) - Linux manual page

【异常错误】Compile with `TORCH_USE_CUDA_DSA` to enable device-side assertions.

在运行项目的时候&#xff0c;出现了错误&#xff0c;但是却不知道为什么错误&#xff0c;因为GPU报的错误太抽象 ../aten/src/ATen/native/cuda/Indexing.cu:1239: indexSelectSmallIndex: block: [5,0,0], thread: [82,0,0] Assertion srcIndex < srcSelectDimSize failed…

基于JAVA+SpringBoot+Vue+uniApp小程序的心理健康测试平台

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 该系统由三个核心角色…

维度评分:Kylin Cube设计中的自定义智能

维度评分&#xff1a;Kylin Cube设计中的自定义智能 引言 Apache Kylin是一个高性能的分布式分析引擎&#xff0c;它通过构建数据立方体&#xff08;Cube&#xff09;来加速对大数据集的查询。在Kylin中&#xff0c;维度的自定义评分是一个高级特性&#xff0c;允许用户根据业…

【PVE】新增2.5G网卡作为主网卡暨iperf测速流程

【PVE】新增2.5G网卡作为主网卡暨iperf测速流程 新增网卡 新增网卡的首先当然需要关闭PVE母机&#xff0c;把新网卡插上&#xff0c;我用淘宝遥现金搞了个红包&#xff0c;花了26元买了块SSU的2.5G网卡。说实话这个价位连散热片都没有&#xff0c;确实挺丐的。稍后测下速度看…

移动硬盘有盘符打不开的全方位解决方案

一、现象描述&#xff1a;移动硬盘有盘符却无法访问 在日常的数据存储与传输中&#xff0c;移动硬盘无疑扮演着举足轻重的角色。然而&#xff0c;不少用户可能会遇到这样一个令人头疼的问题&#xff1a;移动硬盘在连接电脑后&#xff0c;虽然能正常显示盘符&#xff0c;但双击…

【算法】单调队列

一、什么是单调队列 单调队列是一种数据结构&#xff0c;其特点是队列中的元素始终保持单调递增或递减&#xff0c;主要用于维护队列中的最小值或最大值。 不同于普通队列只能从队头出队、队尾入队&#xff0c;单调队列为了维护其特征&#xff0c;还允许从队尾出队 不管怎么…

深入Linux:权限管理与常用命令详解

文章目录 ❤️Linux常用指令&#x1fa77;zip/unzip指令&#x1fa77;tar指令&#x1fa77;bc指令&#x1fa77;uname指令&#x1fa77;shutdown指令 ❤️shell命令以及原理❤️什么是 Shell 命令❤️Linux权限管理的概念❤️Linux权限管理&#x1fa77;文件访问者的分类&#…