C和C++实现stack的对比

本篇文章,我们将对比C语言和C++实现栈的不同来体会C++的魅力!

1.栈的介绍

栈(Stack)是一种常见的数据结构,它是一种特殊的线性表,只允许在一端进行数据的插入和删除操作。这一端通常被称为栈顶(Top),而另一端则被称为栈底(Bottom)。栈的操作遵循后进先出(Last In First Out,简称LIFO)的原则,即最后进入栈的元素将会最先被移除。 

1.1基本特征

  • 后进先出:最后插入的元素最先被删除。
  • 单端操作:所有的插入和删除操作都在栈顶进行。
  • 动态大小:栈的大小可以根据需要动态调整,但在某些实现中,栈的大小可能是固定的。
     

1.2基本操作

  • 初始化(Initialize):创建一个空的栈。
  • 压栈(Push):在栈顶插入一个新的元素。
  • 出栈(Pop):从栈顶删除一个元素,并返回该元素。
  • 获取栈顶元素(Peek/Top):返回栈顶元素的值,但不删除该元素。
  • 判断栈是否为空(IsEmpty):检查栈是否为空。
  • 获取栈的大小(Size):返回栈中元素的数量。
  • 清空栈(Clear):移除栈中的所有元素。
  • 销毁栈(Destroy):释放栈所占用的内存资源

1.3实现方式

  • 数组实现:使用数组来存储栈中的元素,栈的大小在创建时确定,可能存在上溢问题。
  • 链表实现:使用链表来存储栈中的元素,链栈没有固定的大小限制,可以动态扩展。  

1.4应用场景

  • 函数调用:在程序中,函数调用的顺序通常使用栈来管理。
  • 表达式求值:在计算表达式时,使用栈来存储操作数和运算符。
  • 括号匹配:检查括号是否成对出现,常用于编译器的语法分析。
  • 逆波兰表达式转换:将中缀表达式转换为后缀表达式(逆波兰表达式)。 

栈是一种非常高效的数据结构,因为它只允许在一端进行操作,这使得插入和删除操作的时间复杂度都是O(1)。在许多编程语言中,栈已经作为内置的数据类型被实现,如C++中的stack,Java中的Stack类等。 

2.C语言实现栈

stack.c

#include<stdio.h>
#include<assert.h>
typedef int DataType;
typedef struct Stack
{DataType* array;int capacity;int size;
}Stack;void StackInit(Stack* ps)
{assert(ps);ps->array = (DataType*)malloc(sizeof(DataType) * 3);if (NULL == ps->array){assert(0);return;}ps->capacity = 3;ps->size = 0;
}void StackDestroy(Stack* ps)
{assert(ps);if (ps->array){free(ps->array);ps->array = NULL;ps->capacity = 0;ps->size = 0;}
}void CheckCapacity(Stack* ps)
{if (ps->size == ps->capacity){int newcapacity = ps->capacity * 2;DataType* temp = (DataType*)realloc(ps->array, newcapacity * sizeof(DataType));if (temp == NULL){perror("realloc申请空间失败!!");return;}ps->array = temp;ps->capacity = newcapacity;}
}
void StackPush(Stack* ps, DataType data)
{assert(ps);CheckCapacity(ps);ps->array[ps->size] = data;ps->size++;
}int StackEmpty(Stack* ps)
{assert(ps);return 0 == ps->size;
}void StackPop(Stack* ps)
{if (StackEmpty(ps))return;ps->size--;
}DataType StackTop(Stack* ps)
{assert(!StackEmpty(ps));return ps->array[ps->size - 1];
}int StackSize(Stack* ps)
{assert(ps);return ps->size;
}

test.c

int main()
{Stack s;StackInit(&s);StackPush(&s, 1);StackPush(&s, 2);StackPush(&s, 3);StackPush(&s, 4);printf("%d\n", StackTop(&s));printf("%d\n", StackSize(&s));StackPop(&s);StackPop(&s);printf("%d\n", StackTop(&s));printf("%d\n", StackSize(&s));StackDestroy(&s);return 0;
}

 从以上代码,我们可以看到,用C语言实现栈时,Stack相关操作函数有以下共性

  • 每个函数的第一个参数都是Stack*
  • 函数中必须要对第一个参数检测,因为该参数可能是NULL
  • 函数中都是通过Stack*参数来操作栈的
  • 调用时必须传递Stack结构体变量的地址

 结构体中只能定义存放数据的结构,操作数据的方法不能放在结构体里,即数据和操作数据的方式是分离开的。

3.C++实现栈(手搓版ovo) 

stack.cpp

typedef int DataType;
class Stack
{
public:void Init(){_array = (DataType*)malloc(sizeof(DataType*) * 3);if (NULL == _array){perror("malloc申请空间失败");return;}_capacity = 3;_size = 0;}void Push(DataType data){CheckCapacity();_array[_size] = data;_size++;}void Pop(){if (Empty())return;_size--;}DataType Top() { return _array[_size - 1]; }int Empty() { return 0 == _size; }int Size() { return _size; }void Destroy(){if (_array){free(_array);_array = NULL;_capacity = 0;_size = 0;}}
private:void CheckCapacity(){if (_size == _capacity){int newcapacity = _capacity * 2;DataType* temp = (DataType&)realloc(_array, newcapacity * sizeof(DataType));if (temp == NULL){perror("realloc申请空间失败");return;}_array = temp;_capacity = newcapacity;}}
private:DataType* _array;int _capacity;int _size;
};

test.cpp

int main()
{Stack s;s.Init();s.Push(1);s.Push(2);s.Push(3);s.Push(4);printf("%d\n", s.Top());printf("%d\n", s.Size());s.Destroy();return 0;
}

 C++通过类可以将数据以及操作数据的方法进行完美结合,通过访问权限可以控制那些方法在类外被调用,即封装,在使用时就像使用自己的成员一样,更符合人类对一件事情的认知。

而且每个方法不需要传递Stack*的参数了,编译器编译之后该参数会自动还原。即C++中Stack*参数是编译器维护的,C语言需要自己维护。

总之,从C语言到C++实现Stack类的转变,可以明显体会到C++在面向对象编程、封装、代码复用、异常处理等方面的优势。这些特性使得C++更适合于开发大型、复杂的应用程序 。

 

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

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

相关文章

路由器ARP和ARP-proxy(华为)

#交换设备 路由器ARP和ARP-proxy(华为) 当一个广播域中的主机想要访问另外一个广播域的主机时&#xff0c;会广播ARP报文&#xff0c;询问目标IP地址所对应的MAC地址&#xff0c;默认情况下&#xff0c;arp记录是设备自动生成的&#xff0c;但是这样会容易受到ARP欺骗攻击&am…

python实训day4

1、查看数据库的版本 2、查看当前用户 3、查看当前数据库 4、计算表达式的结果; 任何一个数据库,无论大小,都首先是一个超级计算器 5、查看当前MySQL环境中所有的数据库; 系统数据库(只能看)和自定义数据库(任何操作) 6、先建数据库 gaoming 7、如果表已经存在,则创建不能成功 …

【ai】tx2 nx: jetson Triton Inference Server 运行YOLOv4

【ai】tx2 nx: jetson Triton Inference Server 部署YOLOv4 部署了服务端。需要对其测试【ai】tx2-nx 查看 jetpack 版本信息及对应的tritonserver【ai】tx2-nx:配置tritonserver2.17.0-jetpack4.6 环境并运行例子C++ Triton YoloV4 client 是基于 r21.05的 服务端的tensort 的…

springboot3 连接 oceanbase + logproxy数据同步到redis

我这用的是 社区版的 单机&#xff0c; rocky liunx 安装oceanbase 注意事项&#xff1a; logproxy 是 CDC 模式 &#xff0c; springboot 可以直接订阅 canal 是 binlog模式&#xff0c; canal 订阅 logproxy&#xff0c; springboot 订阅 canal logproxy 也可以转 bi…

嵌入式实验---实验七 SPI通信实验

一、实验目的 1、掌握STM32F103SPI通信程序设计流程&#xff1b; 2、熟悉STM32固件库的基本使用。 二、实验原理 1、使用STM32F103R6通过74HC595控制一位LID数码管&#xff0c;实现以下两个要求&#xff1a; &#xff08;1&#xff09;数码管从0到9循环显示&#xff1b; …

无人机巡检小羊仿真

详细视频地址 仿真效果 可视化三维仿真 gazebo物理仿真 px4 飞控仿真 仿qgc简易地面站 详细视频地址

计算机组成原理 | CPU子系统(1)基本概述

基本结构模型 运算与缓存部件 数据寄存部件 PSW不是很清楚 存储器是什么&#xff1f;属于那个结构里&#xff1f; 时序处理部件 cpu是大脑&#xff0c;控制器是神经元 ①通过硬件产生控制信号 ②通过软件产生控制信号 外频&#xff08;系统时钟信号&#xff09;&#xff0c;…

我是如何在markdown编辑器中完成视频的插入和播放的

如果你有更好用的编辑器组件&#xff0c;请一定推荐给我!!!&#xff08;最好附带使用说明&#x1f913;️&#xff09; 介绍 在开发一个社区页面的时候&#xff0c;需要完成发帖、浏览帖子的能力。这里考虑接入markdown编辑器进行开发&#xff0c;也符合大多数用户的习惯。 …

板凳--------第20章-信号:基本概念1

tlpi_hdr.h头文件使用及设置 liao__ran 于 2020-09-29 15:12:01 发布 阅读量1.6k 收藏 5 点赞数 1 分类专栏&#xff1a; linux系统编程手册 版权 linux系统编程手册 专栏收录该内容 7 篇文章 1 订阅 订阅专栏 使用的头文件&#xff0c;主要如下&#xff1a; ename.c.inc erro…

7.XSS获取键盘记录(存储型xss)

什么是跨域 http:// www . xyz.com : 8080 / script/test.js 协议 子域名 主域名 端口 资源地址 当协议、主机&#xff08;主域名&#xff0c;子域名&#xff09;、端口中的任意一个不相同时&#xff0c;称为不同域 我们把不同的域之间请求数据的操作&#xff0c;成为跨域操作…

MOC和MCS通讯流程分析

半导体行业-SECS/GEM协议 半导体设备通讯SECS协议是由国际半导体设备与材料协会&#xff08;SEMI&#xff09;的会员一起构建的连接性标准。它最初是为了在半导体/电子行业的自动化中实现设备与主机系统之间的通信而制定的。 SECS/GEM不仅允许客户查看设备的功能&#xff0c;…

GandCrab5.2勒索病毒复现

GandCrab第一代勒索病毒首次出现于2018年1月&#xff0c;后面经历了五个大版本的更新迭代&#xff0c;该系列病毒特征是采用RSAAES加密算法&#xff0c;从算法上分析解密难度较大&#xff0c;会将系统中的大部分文件加密为随机后缀名的文件&#xff0c;然后对用户进行勒索。本实…

8.12 矢量图层面要素单一符号使用六(SVG填充)

文章目录 前言SVG填充&#xff08;SVG fill&#xff09;QGis设置面符号为SVG填充&#xff08;SVG fill&#xff09;SVG填充&#xff08;SVG fill&#xff09; 总结 前言 本章介绍矢量图层线要素单一符号中使用SVG填充&#xff08;SVG fill&#xff09;的使用说明&#xff1a;文…

ARM相关理论知识

一、计算机的组成 1.输入设备&#xff1a;将数据与程序转换成计算机能够识别&#xff0c;存储&#xff0c;运算的形式&#xff0c;输送到计算机中。 2.输出设备&#xff1a;将计算机对程序和数据的运算结果输送到计算机外部设备 3.控制器&#xff1a;由程序技术器&#xff0…

SpringMVC系列十: 中文乱码处理与JSON处理

文章目录 中文乱码处理自定义中文乱码过滤器Spring提供的过滤器处理中文 处理json和HttpMessageConverter<T>处理JSON-ResponseBody处理JSON-RequestBody处理JSON-注意事项和细节HttpMessageConverter<T\>文件下载-ResponseEntity<T\>作业布置 上一讲, 我们学…

假冒国企现形记:股权变更视角下的甄别分析

启信慧眼-启信宝企业版 假冒国企公告2024-06-07&#xff0c;中粮集团有限公司官网发布《关于冒名中粮企业名单公告》。公告显示&#xff0c;”有不法分子通过伪造相关材料等方式&#xff0c;以我集团子公司名义开展业务&#xff0c;进行虚假宣传。经核实&#xff0c;上述公司假…

伸展树(数据结构篇)

数据结构之伸展树 伸展树 概念&#xff1a; 伸展树是一颗对任意一个节点被访问后&#xff0c;就经过一系列的AVL树的旋转操作将该节点放到根上的特殊二叉查找树。伸展树能保证对树操作M次的时间复杂度为O(MlogN)&#xff0c;而当一个查找树的一个节点刚好处于查找树最坏的情…

物联网系统运维——实验备份与恢复,数据镜像软件DRBD介绍,DRBD的安装和应用,extundelete的安装和应用(重点),环境准备,配置设置

一.数据备份 1.数据备份的重要性 备份是系统中需要考虑的最重要的事项,虽然这在系统的整个规划,开发和测试过程中甚至占不到1%,看似不太重要且默默无闻的工作只有到恢复的时候才能真正体现出其重要性,任何数据的丢失与数据宕机&#xff0c;都是不可以被接收的。 2.数据备份策…

基于Pytorch框架构建LeNet-5模型

Pytorch 一、训练模型1.导入必要的库2.设置超参数3.数据预处理4.读取数据 二、定义卷积神经网络1.定义卷积神经网络2.定义学习率3.实例化模型并且移动到GPU4.选择优化器 三、定义调整学习率的函数1.定义调整学习率的函数 四、训练模型1.设置模型为训练模式2.遍历训练数据加载器…

【Day02】0基础微信小程序入门-学习笔记

文章目录 模板与配置学习目标WXML 模板语法1.数据绑定&#xff08;类似于 Vue2 &#xff09;2. 事件绑定3. 条件渲染4.列表渲染 WXSS模板样式1. rpx尺寸单位2.样式导入3. 全局样式和局部样式 全局配置1. window2. tabBar 页面配置网络数据请求总结 持续更新~ 模板与配置 学习目…