C/C++数据结构之动态数组篇

这篇具有很好参考价值的文章主要介绍了C/C++数据结构之动态数组篇。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

数据结构之——动态数组(顺序表)

1.动态数组和静态数组

静态数组:静态数组在内存中位于栈区,是在编译时就已经在栈上分配了固定大小,程序结束由系统释放。在运行时不能改变数组大小。

//静态数组
	int N = 10;
	int a[N];	/*定义一个数组大小为10的数组,因为静态数组在编译阶段就会确定数组大小,所以这里的N必须是一个确定的值
	如果在这里没有给出N值的大小,会导致编译失败*/

动态数组:动态数组是malloc(在c语言中使用malloc函数)或者new(在c++中使用new操作符)出来的,位于内存的堆区,它的大小是在程序运行时给定的,可以动态的改变数组的大小,以及动态的增,删,查,改数组中的元素。

//动态数组
struct Array
{
	int* a;		//这里只需要定义一个指针,在程序运行起来之后如果在堆区开辟了一块数组空间,就让这个指针指向数组的首地址即可
	int size;   //size用于记录当前数组储存了多少个元素
	int acpcaity;	//acpcaity用于记录当前数组的容量大小(该数组最多能存储多少个元素)
}

2.如何维护一个动态数组

c++动态数组,数据结构,数据结构,c语言,c++
根据上图将维护一个数组分为以下三点:
1.当数组未创建时只需要让arr指针指向NULL,size,acpcaity都初始化为零,当成功在堆区创建了一个数组之后我们只需要把arr指针指向该数组的首地址即可。

2.每次对数组进行添加元素或者删除元素时,都要对应的对size进行相应的加减操作,size必须准确的记录数组中的元素个数

3.每次对数组扩容时都要实时更新当前数组大小给acpcaity,以便于更准确的控制数组大小如果acpcaity大于数组真实容量,可能导致程序崩溃。
列: 如果当前acpcaity=5;而当前数组实际容量为4,这时通过arr[4]插入第5个元素时,就会因为非法访问内存而导致程序崩溃

如果acpcaity小于数组真实容量,会导致数组频繁扩容,造成资源浪费。

以下是一个动态数组的小案列,用C语言实现c++中的vector容器(没有学过的c++的家人们完全可以忽略这句话,因为这就是一个简单动态数组的实现,vector容器的底层也是用动态数组实现的)

//头文件(vector.h)
#pragma once
#include<stdio.h>

//如果想储存其他数据类型只需将这里的int换成你想要储存的数据类型即可
typedef int anytype;	//储存int类型的数据
//typedef double anytype;     //储存double类型的数据

typedef struct STL_Vector
{
	anytype* arr;		//定义一个指针,用于指向后面创建的数组的首地址
	int size;			//记录数组当前元素个数
	int capacity;		//记录数组当前容量大小
}vector;

//接口函数
void VectorInit(vector * v);				 //初始化结构体
void Add_Capacity(vector* v);			  	 //当数组容量不够时扩容
void push_back(vector* v, anytype x);		 //尾部插入元素
void push_front(vector* v, anytype x);		 //头部插入元素
void My_print(vector v);					 //遍历数组
void pop_back(vector* v);					 //删除最后一个元素
int find(vector v, anytype x);				 //查找指定元素的位置,返回元素位置
void pop_front(vector* v);					 //删除第一个元素下标
int pos_insert(vector* v,int pos, anytype x);//指定下标位置插入元素
int pos_delect(vector* v, int pos);			 //指定下标位置删除元素

以下是接口函数的实现

//.c文件(vector.c)
#include"vector.h"
//初始化结构体
void VectorInit(vector* v){
	v->arr = NULL;
	v->capacity = v->size = 0;
}
//创建数组或对已经满的数组进行扩容
void Add_Capacity(vector* v){
	if (v->size == v->capacity){	//当size=capacity时,说明数组可能还未创建,或数组已经满了
		int newspace = v->capacity == 0 ? 4 : v->capacity * 2;	/*如果数组容量为零就先给4个整形的大小,否则就在原来的
		基础上乘以2,每次扩容2倍*/
		anytype* tem = (anytype*)realloc(v->arr, newspace * sizeof(anytype));
		/*1.扩容成功,返回新空间的地址
		  2.扩容失败,返回NULL*/
		if (tem == NULL){
			printf("扩容失败!");
			exit(-1); //扩容失败直接退出程序
		}
		v->arr = tem;  
		v->capacity = newspace;
	}
}
//尾插数据
void push_back(vector* v, anytype x){
	Add_Capacity(v); //首先要确定数组是否创建,容量是否大于零,如果数据未创建,先创建数组,如果已创建但是容量已满,就扩容
	if (v->arr != NULL){
		v->arr[v->size] = x;
		v->size++;
	}
		
}
//头插数据
void push_front(vector* v, anytype x){
	Add_Capacity(v);
	int ret = v->size;
	for (ret; ret>=0; ret--){
		v->arr[ret] = v->arr[ret-1];
	}
	if (v->arr != NULL){
		v->arr[0] = x;
		v->size++;
	}

}
//尾删数据
void pop_back(vector* v){
	if (v->size > 0){   //首先判断数组中是否有数据,有数据才删除,以下同理
		v->size--;
	}
}
//头删数据
void pop_front(vector* v){
	if (v->size > 0){
		int ret = v->size;
		for (int i= 0; i<ret; i++){
			v->arr[i] = v->arr[i+1];
		}
		v->size--;
	}
	
}
//查找数据,成功返回数据下标,失败返回-1
int find(vector v, anytype x){
	if (v.size > 0){
		for (int i = 0; i < v.size; i++){
			if (v.arr[i] == x){
				return i;
			}
		}
	}
	return -1;
}
//指定下标添加数据
int pos_insert(vector* v, int pos, anytype x){
	Add_Capacity(v);
	if (pos >= 0 && pos <= v->size){
		int i = v->size;
		for (i - 1; pos <= i; i--){
			v->arr[i] = v->arr[i-1];
		}
		v->arr[pos] = x;
		v->size++;
		return 0;
	}
	return -1;
}
//指定下标删除数据
int pos_delect(vector* v, int pos){
	Add_Capacity(v);
	if (pos >= 0 && pos < v->size){
		int i = v->size;
		for (pos; pos < i; pos++){
			v->arr[pos] = v->arr[pos+1];
		}
		v->size--;
		return 0;
	}
	return -1;
}
//遍历数组
void My_print(vector v){
	if (v.arr == NULL){
		printf("数组未创建!\n");
		return;
	}
	else if (v.size == 0){
		printf("数组为空!\n");
		return;
	}
	for (int i=0; i < v.size; i++){
		printf("%d ",v.arr[i]);
	}
	printf("\n");
}

3.动态数组和静态数组的优缺点

静态数组
优点:
(1).容量大小固定,下标固定,查找数据快,效率高
缺点:
(1).如果数组满了,就不能继续插入数据了
(2). 很难确定数组的容量大小,给大了浪费,给大小不够放
(3).同一个数组只能储存一种数据类型
动态数组
优点:
(1).可以根据数据量的大小动态扩容和缩小容量
(2).可以通过下标快速查找数据
缺点:
(1).头插数据,中间插入数据时,需要挪动数据,速度慢效率低
(2).同一个数组只能储存一种数据类型

面试常见考点

1.请你说说delete和free的区别

(1). delete是操作符,free是库函数
(2). delete用于在c++中释放new创建的空间,free用于释放c语言中malloc创建的空间
(3). 调用free之前需要检查要释放的指针是否为空,而delete则不需要

2.请你说说malloc和new的区别

(1).new/delete是C++操作符,需要编译器支持,而malloc/free是库函数,需要引入头文件。

(2).使用new操作符申请内存分配时无须指定内存块的大小,编译器会根据类型信息自行计算。而malloc则需要指定要开辟空间的大小。

(3). new操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象匹配,无须进行类型转换,故new是符合类型安全性的操作符。而malloc内存分配成功则是返回void * ,需要通过强制类型转换将void*指针转换成我们需要的类型。

(4).new内存分配失败时,会抛出bac_alloc异常。malloc分配内存失败时返回NULL。

(5). new会先调用operator new函数,申请足够的内存(通常底层使用malloc实现)。然后调用类型的构造函数,初始化成员变量,最后返回自定义类型指针。delete先调用析构函数,然后调用operator delete函数释放内存(通常底层使用free实现)。

(6). C++允许重载new/delete操作符,特别的,布局new的就不需要为对象分配内存,而是指定了一个地址作为内存起始区域,new在这段内存上为对象调用构造函数完成初始化工作,并返回此地址。而malloc不允许重载。

(7).new操作符从自由存储区(free store)上为对象动态分配内存空间,而malloc函数从堆上动态分配内存。自由存储区是C++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区。而堆是操作系统中的术语,是操作系统所维护的一块特殊内存,用于程序的内存动态分配,C语言使用malloc从堆上分配内存,使用free释放已分配的对应内存。自由存储区不等于堆,如上所述,布局new就可以不位于堆中。
转载自

总结

顺序表应该是数据结构中最简单的一个了,接下来的时间我也会更加努力的学习,提升自己的同时给家人们带来更优质的文章,最后希望该篇文章能帮助到大家,作者本人水平有限,如果文章中错误或者不足的地方欢迎大家指出。文章来源地址https://www.toymoban.com/news/detail-590650.html

到了这里,关于C/C++数据结构之动态数组篇的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构03:栈、队列和数组 队习题01[C++]

       考研笔记整理~🥝🥝 之前的博文链接在此:数据结构03:栈、队列和数组_-CSDN博客~🥝🥝 本篇作为链表的代码补充,供小伙伴们参考~🥝🥝 第1版:王道书的课后习题~🧩🧩 编辑: 梅头脑🌸 参考用书: 王道考研《2025年 数据结构考研复习指导》 目录 🧵01 不牺牲存储单

    2024年04月13日
    浏览(30)
  • 【C语言 数据结构】数组与对称矩阵的压缩存储

    提到数组,大家首先会想到的是:很多编程语言中都提供有数组这种数据类型,比如 C/C++、Java、Go、C# 等。但本节我要讲解的不是作为数据类型的数组,而是数据结构中提供的一种叫数组的存储结构。 和线性存储结构相比,数组最大的不同是:它存储的数据可以包含多种“一

    2024年02月04日
    浏览(48)
  • 头歌(C语言)-数据结构与算法-数组(共7关)

    任务描述 本关任务:将十个数进行从大到小的顺序进行排列。 相关知识(略) 编程要求 根据提示,在右侧编辑器 Begin-End 处补充代码。 输入 输入十个整数。 输出 以从大到小的顺序输出这个十个数。 测试说明 样例输入: 1 2 3 4 5 6 7 8 9 10 样例输出: 10 9 8 7 6 5 4 3 2 1 代码:

    2024年02月11日
    浏览(42)
  • 数据结构与算法—一维数组、二维数组、矩阵、顺序串、链接串的C++代码实现

    1、一维数组:ArrayOneD.h 数组这种数据结构可以看作线性表的推广。数组一般采用顺序存储的方法表示。 这是一个模板类 ArrayOneD 的实现,用于表示一维数组。它包括了 构造函数、拷贝构造函数、析构函数、重载下标运算符、重载赋值运算符、求数组长度、重新设置数组长度

    2024年02月07日
    浏览(62)
  • C语言自定义数据类型(二)使用结构体数组

    一个结构体变量中可以存放一组有关联的数据(如一个学生的学号、姓名、成绩等数据)。如果有 10 个学生的数据需要参加运算,显然应该用数组,这就是结构体数组。结构体数组与以前介绍过的数值型数组的不同之处在于每个数组元素都是一个结构体类型的数据,它们都分别

    2024年01月19日
    浏览(49)
  • 【JavaSE专栏48】Java集合类ArrayList解析,这个动态数组数据结构你了解吗?

    作者主页 :Designer 小郑 作者简介 :3年JAVA全栈开发经验,专注JAVA技术、系统定制、远程指导,致力于企业数字化转型,CSDN学院、蓝桥云课认证讲师。 主打方向 :Vue、SpringBoot、微信小程序 本文讲解了 Java 中集合类 ArrayList 的语法、使用说明和应用场景,并给出了样例代码。

    2024年02月16日
    浏览(60)
  • 数据结构与算法教程,数据结构C语言版教程!(第五部分、数组和广义表详解)五

    数组和广义表,都用于存储逻辑关系为“一对一”的数据。 数组存储结构,99% 的编程语言都包含的存储结构,用于存储不可再分的单一数据;而广义表不同,它还可以存储子广义表。 本章重点从矩阵的角度讨论二维数组的存储,同时讲解广义表的存储结构以及有关其广度和

    2024年01月23日
    浏览(50)
  • 数据结构与算法教程,数据结构C语言版教程!(第五部分、数组和广义表详解)三

    数组和广义表,都用于存储逻辑关系为“一对一”的数据。 数组存储结构,99% 的编程语言都包含的存储结构,用于存储不可再分的单一数据;而广义表不同,它还可以存储子广义表。 本章重点从矩阵的角度讨论二维数组的存储,同时讲解广义表的存储结构以及有关其广度和

    2024年01月21日
    浏览(48)
  • 数据结构 | 寻找二维数组的最大值和对应下标 | C语言代码

    题目:         本题目要求读入M(最大为10)行N(最大为15)列个元素,找出其中最大的元素,并输出其行列值。 输入格式:         输入在第一行中给出行数m和列数n。接下来输入m*n个整数。 输出格式:         输出最大值的行号,列号,值。 输入样例: 2 3 1 2 3 4 5 6 输

    2024年02月05日
    浏览(53)
  • 从0开始学C++ 第二十七课 数据结构入门 - 数组与链表

    第二十七课:数据结构入门 - 数组与链表 学习目标: 理解数组的基本概念和操作。 掌握链表的基本结构与特点。 学会在C++中定义和操作数组和链表。 了解数组和链表的基本使用场景。 学习内容: 数组(Array) 概念:数组是一种线性数据结构,用一段连续的内存空间来存储

    2024年01月23日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包