数据结构——顺序栈与链式栈的实现

目录

一、概念

1、栈的定义

2、栈顶

3、栈底

二、接口

1、可写接口

1)数据入栈

2)数据出栈

3)清空栈

2、只读接口

1)获取栈顶数据

2)获取栈元素个数

3)栈的判空

三、栈的基本运算

四、顺序栈(Sequential Stack)实现

1、数据结构定义

2、创建栈

3、清空栈

4、判断栈是否为空

5、判断栈是否饱和

6、入栈

7、出栈

8、取栈顶元素

9、释放malloc申请的内存

打印栈中所有元素示例

五、栈的链表实现

1、数据结构定义

2、创建栈

3、清空栈

4、判断栈是否为空

5、入栈

6、出栈

7、取栈顶元素

8、释放malloc申请的内存

打印栈中所有元素示例

六、两种实现的优缺点

1、顺序表实现

2、链表实现


一、概念

1、栈的定义

   是仅限在 表尾 进行 插入 和 删除 的 线性表
   又被称为 后进先出 (Last In First Out) 的线性表,简称 LIFO 。

2、栈顶

   是一个线性表,我们把允许 插入 和 删除 的一端称为 栈顶

3、栈底

  和 栈顶 相对,另一端称为 栈底,实际上,栈底的元素我们不需要关心。

二、接口

1、可写接口

1)数据入栈

  栈的插入操作,叫做 入栈,也可称为 进栈、压栈。如下图所示,代表了三次入栈操作:

2)数据出栈

  栈的删除操作,叫做 出栈,也可称为 弹栈。如下图所示,代表了两次出栈操作:
在这里插入图片描述

3)清空栈

  一直 出栈,直到栈为空,如下图所示:

2、只读接口

1)获取栈顶数据

  对于一个栈来说只能获取 栈顶 数据,一般不支持获取 其它数据。

2)获取栈元素个数

  栈元素个数一般用一个额外变量存储,入栈 时加一,出栈 时减一。这样获取栈元素的时候就不需要遍历整个栈。通过 �(1)O(1) 的时间复杂度获取栈元素个数。

3)栈的判空

  当栈元素个数为零时,就是一个空栈,空栈不允许 出栈 操作。

三、栈的基本运算

创建空栈 : CreateStack (len)

清空栈 : ClearStack (S)

判断是否栈空 : EmptyStack (S)

判断是否栈满 : FullStack (S)

元素进栈 : PushStack (S,x)

元素出栈 : PopStack (S)

取栈顶元素 : GetTop (S)

四、顺序栈(Sequential Stack)实现

1、数据结构定义

对于顺序表,在 C语言 中表现为 数组,在进行 栈的定义 之前,我们需要考虑以下几个点:
  1)栈数据的存储方式,以及栈数据的数据类型;
  2)栈的大小;
  3)栈顶指针;

  • 我们可以定义一个  的 结构体,C语言实现如下所示:
typedef int datatype;
typedef struct node{     /*定义栈中数据元素的数据类型*/datatype *data;      /*用指针指向栈的存储空间*/int maxlen;          /*当前栈的最大元素个数*/int top;             /*指示栈顶位置(数组下标)的变量*/
}sqstack;                /*顺序栈类型定义*/

2、创建栈

C语言实现如下所示:

sqstack* stack_create(int len)
{sqstack *s;if((s=(sqstack *)malloc(sizeof(sqstack)))==NULL){puts("malloc failed");return NULL;}if((s->data=(datatype *)malloc(len*sizeof(datatype)))==NULL){puts("malloc failed");return NULL;}s->maxlen=len;s->top=-1;return s;
}

3、清空栈

C语言实现如下所示:

void stack_clear(sqstack* s)
{s->top = -1;
}

4、判断栈是否为空

C语言实现如下所示:

int stack_empty(sqstack* s)
{return (s->top==-1 ? 1:0);
}

5、判断栈是否饱和

C语言实现如下所示:

int stack_full(sqstack* s)
{return (s->top==(s->maxlen-1) ? 1:0);
}

6、入栈

C语言实现如下所示:

int stack_push(sqstack* s,datatype value)
{if(s->top==s->maxlen-1){puts("stack is full");return -1;}s->data[s->top+1]=value;s->top++;return 1;
}

7、出栈

C语言实现如下所示:

datatype stack_pop(sqstack* s)
{s->top--;return s->data[s->top+1];
}

8、取栈顶元素

C语言实现如下所示:

datatype stack_top(sqstack* s)
{return(s->data[s->top]);
}

9、释放malloc申请的内存

C语言实现如下所示:

void stack_free(sqstack *s)
{free(s->data);s->data=NULL;free(s);s=NULL;
}

打印栈中所有元素示例

C语言实现如下所示:

sqstack.h

#ifndef __LINKLIST_H__
#define __LINKLIST_H__#include <stdio.h>
#include <stdlib.h>
typedef int datatype;typedef struct node{datatype *data;int maxlen;int top;
}sqstack;extern sqstack* stack_create(int len);
extern int stack_empty(sqstack* s);
extern int stack_full(sqstack* s);
extern void stack_clear(sqstack* s);
extern int stack_push(sqstack* s,datatype value);
extern datatype stack_pop(sqstack* s);
extern datatype stack_top(sqstack* s);
extern void stack_free(sqstack *s);#endif

sqstack.c

#include "sqstack.h"sqstack* stack_create(int len)
{sqstack *s;if((s=(sqstack *)malloc(sizeof(sqstack)))==NULL){puts("malloc failed");return NULL;}if((s->data=(datatype *)malloc(len*sizeof(datatype)))==NULL){puts("malloc failed");return NULL;}s->maxlen=len;s->top=-1;return s;
}int stack_empty(sqstack* s)
{return (s->top==-1 ? 1:0);
}
int stack_full(sqstack* s)
{return (s->top==(s->maxlen-1) ? 1:0);
}
void stack_clear(sqstack* s)
{s->top = -1;
}
int stack_push(sqstack* s,datatype value)
{if(s->top==s->maxlen-1){puts("stack is full");return -1;}s->data[s->top+1]=value;s->top++;return 1;
}
datatype stack_pop(sqstack* s)
{s->top--;return s->data[s->top+1];
}
datatype stack_top(sqstack* s)
{return(s->data[s->top]);
}
void stack_free(sqstack *s)
{free(s->data);s->data=NULL;free(s);s=NULL;
}

test.c

#include "sqstack.h"int main(int argc, const char *argv[])
{sqstack *s;int n=5;s=stack_create(n);stack_push(s,10);stack_push(s,20);stack_push(s,30);stack_push(s,40);stack_push(s,50);stack_push(s,60);while(!stack_empty(s)){printf("%d ",stack_pop(s));}putchar(10);stack_clear(s);stack_free(s);return 0;
}

Makefile

CC = gcc
CFLAGS =  -g -Walltest:test.o sqstack.o$(CC) $(CFLAGS) -o $@ $^.PHONY:clean
clean:rm  test *.o

-g : 产生符号调试工具(GNU的gdb)所必要的符号资讯,要想对源代码进行调试,我们就必须加入这个选项

-Wall : 表示允许发出gcc所有有用的报警信息

-c : 只是编译不链接,生成目标文件".o"

-o test : 表示把输出文件输出到file里

运行结果:

五、栈的链表实现

1、数据结构定义

对于链表,在进行 栈的定义 之前,我们需要考虑以下几个点:
  1)栈数据的存储方式,以及栈数据的数据类型;
  2)栈的大小;
  3)栈顶指针;

我们可以定义一个  的 结构体,C语言实现如下所示:

typedef int datatype;typedef struct node{datatype data;struct node* next;
}listnode,*linklist;

2、创建栈

C语言实现如下所示:

linklist stack_create()
{linklist s;if((s=(linklist)malloc(sizeof(listnode)))==NULL){puts("malloc failed");return NULL;}s->next=NULL;return s;
}

3、清空栈

C语言实现如下所示:

void stack_clear(linklist s)
{linklist p;printf("clear:");p=s->next;while(p){s->next=p->next;printf("%d ",p->data);free(p);p=s->next;}putchar(10);
}

4、判断栈是否为空

C语言实现如下所示:

int stack_empty(linklist s)
{return (s->next==NULL ? 1:0);
}

5、入栈

C语言实现如下所示:

int stack_push(linklist s,datatype value)
{linklist p;if((p=(linklist)malloc(sizeof(listnode)))==NULL){puts("malloc failed");return -1;}p->data = value;p->next=s->next;s->next = p;return 0;
}

6、出栈

C语言实现如下所示:

datatype stack_pop(linklist s)
{linklist p;datatype ret;p=s->next;s->next=p->next;ret=p->data;free(p);p=NULL;return ret;
}

7、取栈顶元素

C语言实现如下所示:

datatype stack_top(linklist s)
{return (s->next->data);
}

8、释放malloc申请的内存

C语言实现如下所示:

void stack_free(linklist s)
{linklist p;printf("free:");p=s;while(p){s=s->next;printf("%d ",p->data);free(p);p=s;}putchar(10);}

打印栈中所有元素示例

C语言实现如下所示:

linkstack.h        

#ifndef __LINKLIST_H__
#define __LINKLIST_H__#include <stdio.h>
#include <stdlib.h>
typedef int datatype;typedef struct node{datatype data;struct node* next;
}listnode,*linklist;extern linklist stack_create();
extern int stack_empty(linklist s);
extern void stack_clear(linklist s);
extern int stack_push(linklist s,datatype value);
extern datatype stack_pop(linklist s);
extern datatype stack_top(linklist s);
extern void stack_free(linklist s);#endif

linkstack.c

#include "linkstack.h"linklist stack_create()
{linklist s;if((s=(linklist)malloc(sizeof(listnode)))==NULL){puts("malloc failed");return NULL;}s->next=NULL;return s;
}
int stack_empty(linklist s)
{return (s->next==NULL ? 1:0);
}int stack_push(linklist s,datatype value)
{linklist p;if((p=(linklist)malloc(sizeof(listnode)))==NULL){puts("malloc failed");return -1;}p->data = value;p->next=s->next;s->next = p;return 0;
}datatype stack_pop(linklist s)
{linklist p;datatype ret;p=s->next;s->next=p->next;ret=p->data;free(p);p=NULL;return ret;
}datatype stack_top(linklist s)
{return (s->next->data);
}void stack_clear(linklist s)
{linklist p;printf("clear:");p=s->next;while(p){s->next=p->next;printf("%d ",p->data);free(p);p=s->next;}putchar(10);
}
void stack_free(linklist s)
{linklist p;printf("free:");p=s;while(p){s=s->next;printf("%d ",p->data);free(p);p=s;}putchar(10);}

test.c

#include "linkstack.h"int main(int argc, const char *argv[])
{linklist s;s=stack_create();stack_push(s,10);stack_push(s,20);stack_push(s,30);stack_push(s,40);stack_push(s,50);stack_push(s,60);#if 0while(!stack_empty(s)){printf("%d ",stack_pop(s));}putchar(10);
#endif
//	stack_clear(s);stack_free(s);return 0;
}

Makefile

CC = gcc
CFLAGS =  -g -Walltest:test.o linkstack.o$(CC) $(CFLAGS) -o $@ $^.PHONY:clean
clean:rm  test *.o

运行结果:

六、两种实现的优缺点

1、顺序表实现

  在利用顺序表实现栈时,入栈 和 出栈 的常数时间复杂度低,且 清空栈 操作相比 链表实现 能做到 O(1),唯一的不足之处是:需要预先申请好空间,而且当空间不够时,需要进行扩容,扩容方式本文未提及,可以参考大佬文章:《C/C++ 面试 100 例》(四)vector 扩容策略。

2、链表实现

  在利用链表实现栈时,入栈 和 出栈 的常数时间复杂度略高,主要是每插入一个栈元素都需要申请空间,每删除一个栈元素都需要释放空间,且 清空栈 操作是 O(n) 的,直接将 栈顶指针 置空会导致内存泄漏。好处就是:不需要预先分配空间,且在内存允许范围内,可以一直 入栈,没有顺序表的限制。

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

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

相关文章

Linux实战:部署基于Postfix 与 Dovecot 的邮件系统

一、电子邮件系统简介 在电子邮件系统中&#xff0c;为用户收发邮件的服务器名为邮件用户代理&#xff08;Mail User Agent&#xff0c;MUA&#xff09;&#xff0c;MTA &#xff08;邮件传输代理&#xff09;的工作职责是转发处理不同电子邮件服务供应商之间的邮件&#xff0…

目标检测 YOLOv5 - 推理时的数据增强

目标检测 YOLOv5 - 推理时的数据增强 flyfish 版本 YOLOv5 6.2 参考地址 https://github.com/ultralytics/yolov5/issues/303在训练时可以使用数据增强&#xff0c;在推理阶段也可以使用数据增强 在测试使用数据增强有个名字叫做Test-Time Augmentation (TTA) 实际使用中使…

PostgreSQL数据库的json操作

1.操作符 select json字段::json->key值 from order -- 对象域 select json字段::json->>key值 from order -- 文本 select json字段::json#>{key值} from order -- 对象域 select json字段::json#>>{key值} from order -- 文本对象域表示还能继续操作&#…

26、web攻防——通用漏洞SQL注入SqlmapOracleMongodbDB2

文章目录 OracleMongoDBsqlmap SQL注入课程体系&#xff1b; 数据库注入&#xff1a;access、mysql、mssql、oracle、mongodb、postgresql等数据类型注入&#xff1a;数字型、字符型、搜索型、加密型&#xff08;base63 json&#xff09;等提交方式注入&#xff1a;get、post、…

ES6之生成器(Generator)

✨ 专栏介绍 在现代Web开发中&#xff0c;JavaScript已经成为了不可或缺的一部分。它不仅可以为网页增加交互性和动态性&#xff0c;还可以在后端开发中使用Node.js构建高效的服务器端应用程序。作为一种灵活且易学的脚本语言&#xff0c;JavaScript具有广泛的应用场景&#x…

如何使用Git进行代码版本管理

目录 建立仓库 分支管理 推送代码 问题 建立仓库 先在远程代码托管平台&#xff08;如GitHub、GitLab等&#xff09;上创建一个新的仓库 使用命令行或终端&#xff0c;进入你的本地项目目录 如果项目还没有使用Git进行版本控制&#xff0c;可以通过执行以下命令来初始…

Origin 2021软件安装包下载及安装教程

Origin 2021下载链接&#xff1a;https://docs.qq.com/doc/DUnJNb3p4VWJtUUhP 1.选中下载的压缩包&#xff0c;然后鼠标右键选择解压到"Origin 2021"文件夹 2.双击打开“Setup”文件夹 3.选中“Setup.exe”鼠标右键点击“以管理员身份运行” 4.点击“下一步" 5…

240101-5步MacOS自带软件无损快速导出iPhone照片

硬件准备&#xff1a; iphone手机Mac电脑数据线 操作步骤&#xff1a; Step 1: 找到并打开MacOS自带的图像捕捉 Step 2: 通过数据线将iphone与电脑连接Step 3&#xff1a;iphone与电脑提示“是否授权“&#xff1f; >>> “是“Step 4&#xff1a;左上角选择自己的设…

springboot3+vue3实现大文件分片上传和断点续传

大文件分片上传和断点续传 大文件分片上传是一种将大文件切分成小片段进行上传的策略。这种上传方式有以下几个主要原因和优势&#xff1a; 网络稳定性&#xff1a;大文件的上传需要较长时间&#xff0c;而网络连接可能会不稳定或中断。通过将文件切分成小片段进行上传&#xf…

低延时视频技术的应用场景和挑战

编者按 无线网络对人们的生活产生了巨大的影响&#xff0c;而5G技术的引入将彻底改变我们与世界互联互通的方式。在5G时代&#xff0c;实现万物互联离不开低延时技术的应用。 LiveVideoStackCon 2023 深圳站邀请到秒点科技的CEO扶凯&#xff0c;为大家分享低延时技术在物联网、…

【CF比赛记录】—— Good Bye 2023(A、B、C)

&#x1f30f;博客主页&#xff1a;PH_modest的博客主页 &#x1f6a9;当前专栏&#xff1a;CF比赛记录 &#x1f48c;其他专栏&#xff1a; &#x1f534;每日一题 &#x1f7e1; cf闯关练习 &#x1f7e2; C语言跬步积累 &#x1f308;座右铭&#xff1a;广积粮&#xff0c;缓…

Big-endian与Little-endian详尽说明

大端与小端存储详尽说明 大端与小端存储详尽说明 大端与小端存储详尽说明一. 什么是字节序二. 什么是大端存储模式三. 什么是小端存储模式四. 大小端各自的特点五. 为什么会有大小端模式之分六. 为什么要注意大小端问题六. 大小端判定程序七. 大端小端的转换1&#xff09;16位大…

详解Vue3中的鼠标事件mousedown、mouseup和contextmenu

本文主要介绍Vue3中的常见鼠标事件mousedown、mouseup和contextmenu。 目录 一、mousedown——鼠标按下事件二、mouseup——鼠标弹起事件三、contextmenu——页面菜单 下面是Vue 3中常用的鼠标事件mousedown、mouseup和contextmenu的详解。 一、mousedown——鼠标按下事件 mo…

当你的电脑在安装Windows更新后出现问题时怎么办,这里提供办法

Windows更新通常会为你的电脑带来错误修复、安全补丁和新功能,但它们也可能会带来性能下降甚至引发恐慌的数据丢失等问题,从而适得其反。如果你在安装更新后发现了一些奇怪之处,你可以将其回滚,尝试重新启动。 Windows更新主要有两种:质量更新和功能更新。高质量的更新包…

vmware安装openEuler 22.03 LTS操作系统

vmware安装openEuler 22.03 LTS操作系统 1、下载openEuler操作系统镜像文件2、安装openEuler操作系统3、配置openEuler操作系统3.1、配置静态IP地址 和 dns3.2、查看磁盘分区3.3、查看系统版本 1、下载openEuler操作系统镜像文件 官网下载链接 链接: https://www.openeuler.or…

【2023年终总结:轻舟已过万重山】

&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308; 欢迎关注公众号&#xff08;通过文章导读关注&#xff09;&#xff0c;发送【资料】可领取 深入理解 Redis 系列文章结合电商场景讲解 Redis 使用场景、中间件系列…

数据结构期末复习(fengkao课堂)

学习数据结构时&#xff0c;以下建议可能对您有所帮助&#xff1a; 理解基本概念&#xff1a;首先&#xff0c;确保您理解数据结构的基本概念&#xff0c;例如数组、链表、栈、队列、树、图等。了解它们的定义、特点和基本操作。 学习时间复杂度和空间复杂度&#xff1a;了解如…

Docker support for NVIDIA GPU Accelerated Computing on WSL 2

Docker support for NVIDIA GPU Accelerated Computing on WSL 2 0. 背景1. 安装 Docker Desktop2. 配置 Docker Desktop3. WLS Ubuntu 配置4. 安装 Docker-ce5. 安装 NVIDIA Container Toolkit6. 配置 Docker7. 运行一个 Sample Workload 0. 背景 今天尝试一下 NVIDIA GPU 在…

IoT 物联网常用协议

物联网协议是指在物联网环境中用于设备间通信和数据传输的协议。根据不同的作用&#xff0c;物联网协议可分为传输协议、通信协议和行业协议。 传输协议&#xff1a;一般负责子网内设备间的组网及通信。例如 Wi-Fi、Ethernet、NFC、 Zigbee、Bluetooth、GPRS、3G/4G/5G等。这些…

公司电脑文件防泄密|防止内部终端核心文件数据 \ 资料外泄

PC端访问地址&#xff1a; https://isite.baidu.com/site/wjz012xr/2eae091d-1b97-4276-90bc-6757c5dfedee 为了防止公司电脑文件泄密&#xff0c;可以采取以下措施&#xff1a; 文件加密&#xff1a;对重要文件进行加密是一种有效的防泄密方法。通过使用加密算法&#xff0c;…