数据结构 - C/C++ - 数组

目录

结构特性

内存布局

结构样式

结构拓展

数据初始

元素访问

插入元素

删除元素

查找元素

修改元素

结构设计

成员变量

构造函数

功能函数

示例代码


结构特性

  • 长度固定:数组的长度在创建时已经被确定,如果需要动态改变数组的长度,可以考虑使用动态数组。

  • 连续性:数组中的所有元素在内存中是连续存储的。数组可以快速访问任意元素,单插入和删除操作会影响效率。

  • 一致性:数组中的所有元素必须都是相同的类型。

  • 索引:索引从0开始,数组下标上限长度减去1。

内存布局

  • 数组在内存中占据一块连续的内存空间。

  • 数组起始地址是数组首个元素的地址(数组名即为首地址)。

  • 每个元素占据的内存空间是相同的,具体大小取决于与元素的类型。

  • 通过索引可以快速访问数组中的任意元素。

    #include <iostream>int main()
    {int Arr[10] = { 1,3,2,5,4 };printf("Arr.BaseAddr -> %p \r\n", Arr);printf("Arr.BaseAddr -> %p \r\n", &Arr[0]);for (int Index = 0; Index < sizeof(Arr) / sizeof(Arr[0]); Index++){printf("Arr[%d] -> %p -> %d \r\n", Index, &Arr[Index], Arr[Index]);}return 0;
    }
    

 

结构样式

  • 静态数组:编译时确定数组长度,无法在运行期间修改其长度。

  • 动态数组:运行时动态分配内存,可以在运行期间修改其长度。(C++STD::VECTOR)

结构拓展

数据初始

#include <iostream>int main()
{//stackint Arr1[5];int Arr2[5] = { 0 };int Arr3[] = { 1,2,3,4,5 };//heapint* p1 = new int[5];delete[] p1;int* p2 = new int[5]{ 1,2,3,4,5 };delete[] p2;return 0;
}

元素访问

  • 内存图解
  • 实例代码
    • #include <iostream>int main()
      {int Arr[5] = { 1,3,2,5,4 };Arr[0] = 1;Arr[1] = 2;Arr[2] = 3;Arr[3] = 4;Arr[4] = 5;return 0;
      }
  • 汇编分析 
    • 	int Arr[5] = { 1,3,2,5,4 };
      00414635  mov         dword ptr [ebp-18h],1  
      0041463C  mov         dword ptr [ebp-14h],3  
      00414643  mov         dword ptr [ebp-10h],2  
      0041464A  mov         dword ptr [ebp-0Ch],5  
      00414651  mov         dword ptr [ebp-8],4  Arr[0] = 1;
      00414658  mov         eax,4  
      0041465D  imul        ecx,eax,0  
      00414660  mov         dword ptr [ebp+ecx-18h],1  Arr[1] = 2;
      00414668  mov         eax,4  
      0041466D  shl         eax,0  
      00414670  mov         dword ptr [ebp+eax-18h],2  Arr[2] = 3;
      00414678  mov         eax,4  
      0041467D  shl         eax,1  
      0041467F  mov         dword ptr [ebp+eax-18h],3  Arr[3] = 4;
      00414687  mov         eax,4  
      0041468C  imul        ecx,eax,3  
      0041468F  mov         dword ptr [ebp+ecx-18h],4  Arr[4] = 5;
      00414697  mov         eax,4  
      0041469C  shl         eax,2  
      0041469F  mov         dword ptr [ebp+eax-18h],5  
    • ebp-18h == 数组首地址

    • mov dword ptr [ebp+ecx-18h],1 == ebp-18h + 0 * 4

    • mov dword ptr [ebp+eax-18h],2 == ebp-18h + 1 * 4

    • mov dword ptr [ebp+eax-18h],3 == ebp-18h + 2 * 4

    • mov dword ptr [ebp+ecx-18h],4 == ebp-18h + 3 * 4

    • mov dword ptr [ebp+eax-18h],5 == ebp-18h + 4 * 4

插入元素

  • 插入步骤
  • 代码实现
    • void Insert(int* p, int nLength, int nIndex, int nVar)
      {for (int i = nLength - 1; i > nIndex; i--){p[i] = p[i - 1];}p[nIndex] = nVar;
      }

删除元素

  • 删除步骤
  • 代码实现
    • void Remove(int* p, int nLength, int nIndex)
      {for (int i = nIndex; i < nLength - 1; i++){p[i] = p[i + 1];}
      }

查找元素

  • int Find(int* p, int nLength, int nVar)
    {for (int i = 0; i < nLength; i++){if (p[i] == nVar){return i;}}return -1;
    }

修改元素

  • 	int Arr[6] = { 1,2,3,4,5 };Arr[0] = 11;*(Arr + 1) = 22;

结构设计

成员变量

	T*	data;		//动态数组指针int size;		//数组元素个数int capacity;	//数组容量大小

构造函数

  • 默认构造函数
  • 有参构造函数
  • 拷贝构造函数
  • 移动构造函数
  • 列表构造函数

功能函数

  • 元素个数
  • 数组容量
  • 是否为空
  • 下标访问
  • 插入元素
  • 删除元素
  • 查找元素

示例代码

#include <iostream>
#include <vector>template <typename T>
class Vector
{
private:			//成员变量T*	data;		//动态数组指针int size;		//数组元素个数int capacity;	//数组容量大小public:				//构造析构//默认构造函数Vector() : data(nullptr), size(0), capacity(0){}//有参构造函数Vector(int size, const T& var) : size(size), capacity(size){this->data = new T[capacity];for (size_t i = 0; i < capacity; i++){data[i] = var;}}//拷贝构造函数Vector(const Vector& ref) : size(ref.size), capacity(ref.capacity){this->data = new T[capacity];for (size_t i = 0; i < capacity; i++){this->data[i] = ref.data[i];}}//移动构造函数Vector(Vector&& other)noexcept : data(other.data), size(other.size), capacity(other.capacity){other.data = nullptr;other.size = 0;other.capacity = 0;}//列表构造函数Vector(std::initializer_list<T> initlist) : size(initlist.size()), capacity(initlist.size()){this->data = new T[capacity];int i = 0;for (const auto& value: initlist){data[i++] = value;}}//默认析构函数~Vector(){if (this->data != NULL){delete[] this->data;}}public:				//成员函数//获取元素个数int Size() const{return this->size;}//获取数组容量int Capacity() const{return this->capacity;}//数组是否为空bool Empty(){return this->size == 0 ? true : false;}//下标获取元素T& operator[](int nIndex){return this->data[nIndex];}//末尾追加元素void Push_Back(const T& value){//判断容器容量if (this->size >= this->capacity){//容量大小修正capacity = (capacity == 0) ? 1 : capacity * 2;//申请扩容内存T* tempData = new T[capacity];//拷贝默认数据for (int i = 0; i < size; i++){tempData[i] = this->data[i];}//释放默认内存delete[] this->data;//修正数据指针this->data = tempData;}this->data[size] = value;
-		size++;}//插入元素数据void Insert(int nIndex, const T& value){//判断索引序号if (nIndex < 0 || nIndex > size){throw std::out_of_range("Invalid Index");}//判断容器容量if (this->size >= this->capacity){//容量大小修正capacity = (capacity == 0) ? 1 : capacity * 2;//申请扩容内存T* tempData = new T[capacity];//拷贝默认数据for (int i = 0; i < size; i++){tempData[i] = this->data[i];}//释放默认内存delete[] this->data;//修正数据指针this->data = tempData;}//指定位置插入for (int i = size; i > nIndex; i--){this->data[i] = this->data[i - 1];}this->data[nIndex] = value;this->size++;}//删除元素数据void erase(int nIndex){//判断索引序号if (nIndex < 0 || nIndex > size){throw std::out_of_range("Invalid Index");}//删除指定元素for (int i = nIndex; i < this->size -1; i++){this->data[i] = this->data[i + 1];}//修正数组个数//this->data[this->size - 1] = 0;this->size--;}//查找指定元素int Find(const T& valud) const{for (size_t i = 0; i < this->size; i++){if (this->data[i] == valud){return i;}}return -1;}};int main()
{//默认构造函数Vector<int> vec1;//有参构造函数Vector<int> vec2(3, 0xCC);//拷贝构造函数Vector<int> vec3(vec2);//移动构造函数Vector<int> vec4(std::move(vec3));//列表构造函数Vector<int> vec5 = { 1,2,3,4,5 };return 0;
}

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

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

相关文章

C++面向对象程序设计 - 多继承,以及基类与派生类转换

单继承是一个类是从另一个基类派生类而来的&#xff0c;多继承则是一个派生类是同两个或多个基类&#xff0c;派生类从两人或多个基类中继承所需的属性。 声明多重继承的方法&#xff1a; class D: public A, private B, protected C { 类D新增加的成员 } 一、多重继承派生类的…

Vue---组件

Vue—组件 目录 Vue---组件定义组件全局组件局部组件 组件通讯***重点***父子通信之父传子&#xff08;props&#xff09;父子通信之子传父&#xff08;$emit&#xff09;ref属性&#xff08;$refs&#xff09; 动态组件插槽命名插槽 定义组件 全局组件 vue2中template只能传…

浏览器渲染机制:重排(Reflow)与重绘(Repaint)以及Vue优化策略

浏览器渲染机制是一个复杂但有序的过程&#xff0c;其目的是将HTML、CSS和JavaScript代码转化为用户可以看到和交互的视觉界面。重排&#xff08;Reflow&#xff09;与重绘&#xff08;Repaint&#xff09;是浏览器渲染过程中对页面元素进行更新的两个重要步骤&#xff0c;理解…

ubuntu22.04安装TensorRT(过程记录)

重要说明&#xff1a;此贴经过多次修改。第一次安装的的为trt8.6.1版本。第二次安装的10.0.0.6版本。有些地方可能没改过来&#xff0c;比如链接向导&#xff0c;我懒得改了&#xff0c;但是流程是对的。 cuda和cudnn版本对应关系 tensorRT历史发行版本 CUDA历史发行版本 cudn…

ENVI不同版本个人使用对比

ENVI不同版本个人使用对比 文章目录 ENVI不同版本个人使用对比前言对比5.3学习版5.6学习版6.0试用版 总结 前言 目前来看&#xff0c;流传较广的可供大家免费获取的ENVI版本主要是5.3学习版 5.6学习版 6.0学习版这三个版本&#xff0c;不同的版本有不同特色&#xff0c;在此做…

C#基础|StringBuilder字符串如何高效处理。

哈喽&#xff0c;你好&#xff0c;我是雷工。 字符串处理在C#程序开发中是使用频率比较高的&#xff0c;但常规的字符串处理方式对内存占用比较多&#xff0c;为了优化内存&#xff0c;减少不必要的内存浪费&#xff0c;引入了StringBuilder类。 下面学习下StringBuilder类的使…

PC-3000 Flash:NAND 闪存设备(包括一体式U盘)数据恢复的重量级工具(一)

天津鸿萌科贸发展有限公司从事数据安全业务20余年&#xff0c;在数据恢复、数据取证、数据备份等领域有丰富的案例经验、前沿专业技术及良好的行业口碑。同时&#xff0c;公司面向取证机构及数据恢复公司&#xff0c;提供数据恢复实验室建设方案&#xff0c;包含 PC-3000 系列数…

LeetCode 热题 100 Day05

矩阵相关题型 Leetcode 73. 矩阵置零【中等】 题意理解&#xff1a; 将矩阵中0所在位置&#xff0c;行|列置换为全0 其中可以通过记录0元素所在的行、列号&#xff0c;来标记要置换的行|列 将对应位置置换为0 解题思路&#xff1a; 第一个思路&#xff1a; 可以…

React | classnames

classnames 这个库在我们的项目中有大量的使用到&#xff0c;它不仅很实用&#xff0c;还非常好用&#xff0c;但还有人不知道这个库&#xff0c;我真的是十分心痛。 通过 classnames&#xff0c;我们可以给组件设置多个 className&#xff0c;还可以根据需要动态设置 classNa…

模块四:前缀和——DP35 【模板】二维前缀和

文章目录 题目描述算法原理解法一&#xff1a;暴力模拟&#xff08;时间复杂度为O(n*m*q)&#xff09;解法二&#xff1a;二维前缀和&#xff08;时间复杂度为O(m*n)O(q)) 代码实现解法二&#xff1a;前缀和&#xff08;C)Java 题目描述 题目链接&#xff1a;DP35 【模板】二维…

三星电脑文件夹误删了怎么办?恢复方案在此

在使用三星电脑的过程中&#xff0c;我们可能会不小心删除了某个重要的文件夹&#xff0c;其中可能包含了工作文件、家庭照片、视频或其他珍贵的数据。面对这种突发情况&#xff0c;不必过于焦虑。本文将为您提供几种有效的恢复方案&#xff0c;希望能帮助您找回误删的文件夹及…

openEuler-22.03安装 mysql8.0.32

一、下载解压 下载地址&#xff1a; MySQL :: Download MySQL Community Server (Archived Versions) tar -xvf mysql-8.0.32-1.el7.x86_64.rpm-bundle.tar -C /opt/mysql-8.0.32 二、安装 最开始安装一直报错 缺少 libcrypto.so.10库文件,安装openssl可以解决 wget http://…

Java客户端如何直接调用es的API

Java客户端如何直接调用es的API 一. 问题二. withJson 前言 这是我在这个网站整理的笔记,有错误的地方请指出&#xff0c;关注我&#xff0c;接下来还会持续更新。 作者&#xff1a;神的孩子都在歌唱 一. 问题 今天做项目的时候&#xff0c;想要直接通过java客户端调用es的api…

揭秘工业大模型:从人工智能小白到技术先锋

工业大模型的五个基本问题 信息化时代&#xff0c;数字化转型成为企业提升营运效率、应对经营风险和提升核心竞争力的重要途径。在此过程中&#xff0c;数据作为一种客观存在的资源&#xff0c;所产生的价值日益凸显。党的十九届四中全会从国家治理体系和治理能力现代化的高度将…

【万字长文】看完这篇yolov4详解,那算是真会了

前言 目标检测作为计算机视觉领域的一个核心任务&#xff0c;其目的是识别出图像中所有感兴趣的目标&#xff0c;并给出它们的类别和位置。YOLO&#xff08;You Only Look Once&#xff09;系列模型因其检测速度快、性能优异而成为该领域的明星。随着YOLOv4的推出&#xff0c;…

双塔模型在召回和粗排的区别

答案参考&#xff1a;推荐系统中&#xff0c;双塔模型用于粗排和用于召回的区别有哪些? - 知乎 召回和粗排在不同阶段面临样本不一样&#xff0c;对双塔来说样本分布差异会使召回和粗排采取不一样的方式。召回打分空间是全部item空间&#xff0c;曝光只有很少一部分&#xff0…

【机器学习】集成学习---Bagging之随机森林(RF)

【机器学习】集成学习---Bagging之随机森林&#xff08;RF&#xff09; 一、引言1. 简要介绍集成学习的概念及其在机器学习领域的重要性。2. 引出随机森林作为Bagging算法的一个典型应用。 二、随机森林原理1. Bagging算法的基本思想2. 随机森林的构造3. 随机森林的工作机制 三…

ClickHouse 如何实现数据一致性

文章目录 ReplacingMegreTree 引擎数据一致性实现方式1.ReplacingMegreTree 引擎2.ReplacingMegreTree 引擎 手动合并3.ReplacingMegreTree 引擎 FINAL 查询4.ReplacingMegreTree 引擎 标记 GroupBy5.允许偏差 前言&#xff1a;在大数据中&#xff0c;基本上所有组件都要求…

Docker创建镜像之--------------基于Dockerfile创建

目录 一、在编写 Dockerfile 时&#xff0c;有严格的格式需要遵循 二、Dockerfile 操作常用的指令 2.1ENTRYPOINT和CMD共存的情形 2.2ENTRYPOINT和CMD的区别 2.3ADD 与COPY的区别 三、Dockerfile案例 3.1构建apache镜像 3.1.1 创建镜像目录方便管理 3.1.2创建编写dock…

函数递归与迭代

目录 1.递归 1.1递归的思想 1.2递归的限制条件 2.递归与迭代 1.递归 函数递归是什么&#xff1f; 递归是学习C语⾔函数绕不开的⼀个话题&#xff0c;那什么是递归呢? 递归其实是⼀种解决问题的⽅法&#xff0c;在C语⾔中&#xff0c;递归就是函数⾃⼰调⽤⾃⼰。 写⼀个史…