(1)数据结构与算法-动态数组(1)

顺序表

回顾数组

基本概念

1)根据空间分,可分为栈区数组和堆区数组
栈区数组:系统自动管理
堆区数组:我们自己管理malloc/free new/delete

基本操作

节点装的是数据

创建与初始化节点

栈区:int a[4] = {0,1,2,3};
堆区:int *p = (int*)malloc(sizeof(int)*4); free(p);

改、查节点

a.下标运算:[ ]
b.指针运算:*(p+n) = p[n]

增加节点

数组尾部增加
1)数组没空间了,怎么添加?
a.申请时申请足够大的空间
有点浪费空间、用空间换时间
b.动态申请空间(malloc)
思路:再申请一个更大的空间把之前小空间的数组中的数据复制进来,新数据在后面加
优劣:用时间换空间
空间利用率高,但速度慢(涉及 新的申请空间的过程,又涉及到释放原空间,复制原空间的过程)
2)动态空间申请多大?
每次申请空间的时候,就多申请一些。不必申请复制很多次,提高运行速度
3)申请过程
初始化
a.记录首地址malloc时记录首地址
b.记录可存储的数据总量,即容量
c.记录已存储的数据总量:数量,下标记录
这三个元素,就可以用结构体装一起,并初始化:

通过函数修改外部变量的值,就要传递变量的地址
要传地址,参数就要定义成对应类型的指针,如下:

#include<stdio.h>
#include<stdlib.h>

struct DynamicArr
{
	int* Head;  //数组头指针,装首地址
	unsigned int Cap;//容量
	unsigned int Num;//已存储的数量
};
//定义函数,将结构体传入赋值初始化
void iniArr(struct DynamicArr * pArr)  //结构体指针
{
	pArr->Head =(int*) malloc(sizeof(int)*pArr->Cap );
	pArr->Num = 0;  //以后每次添加都加一,Num++
	pArr->Cap = 5;
}
int main(void)
{
	struct DynamicArr Arr;
	iniArr(&Arr);//传地址进行赋值初始化
	//释放空间
	free(Arr.Head);
	system("pause");
	return 0;
}

添加元素
添加元素,创建函数封装特定功能
这里要传的是结构体指针(用于指向成员)和增加的数

void Add(struct DynamicArr * pArr, int AddNum)  {}

进到函数,先判断容量和数量是否相等,相等即装满。装满就要进行操作来申请空间:

//判断是否装满
	if (pArr->Cap == pArr->Num ){}

a.容量变大

//容量变大 一定是先增加空间,再malloc,,不然还是不变
		pArr->Cap += 10; 

b.申请空间

//容量变大 一定是先增加空间,再malloc,,不然还是不变
		pArr->Cap += 10; 
		//申请指针变量装这个新空间,此时的cap是变大的新空间
		int *ptemp = (int*)malloc(sizeof(int*)*pArr->Cap);

c.将原数据赋值进新空间

//将原数据复制新空间
for (unsigned int i = 0; i < pArr->Cap; i++)//从0开始,到容量最大
{
	ptemp[i] = pArr->Head[i]; //Head是数组头指针装首地址
}

d.释放原空间

//释放原空间
	free(pArr->Head);

e.将数组头指针指向新空间

//将数组头指针指向新空间
		pArr->Head = ptemp;	 //将ptemp的新空间赋给Head

f.Head数组指向最后一个元素

//Head[pArr->Num]是指向最后一个元素 将新数据装入最后
pArr->Head[pArr->Num] = AddNum;
//每增加一个元素,就累加一次
pArr->Num++;//累加元素的数量

g.主函数部分

	//调用5次依然不会增加空间,在调用第6次的时候才会增加空间
	Add(&Arr, 3);
	Add(&Arr, 3);
	Add(&Arr, 3);
	Add(&Arr, 3);
	Add(&Arr, 3);
	Add(&Arr, 3);
	printf("%u,%u\n",Arr.Cap ,Arr.Num );//输出容量和数量
	for (int i = 0; i < Arr.Num;i++)
	{
		printf("%d",Arr.Head [i]); //输出数组中的元素
	}

调用5次输出
5,5
3 3 3 3 3
调用6次输出
15,6
3 3 3 3 3 3

整体代码如下:

#include<stdio.h>
#include<stdlib.h>

struct DynamicArr
{
	int *Head;  //数组头指针
	unsigned int Cap;//容量
	unsigned int Num;//已存储的数量
};
//定义函数,将结构体传入赋值
//通过函数修改外部变量的值,就要传递变量的地址了
//要传地址,参数就要定义成对应类型的指针
void iniArr(struct DynamicArr *pArr)  //结构体指针
{
	pArr->Cap = 5;
	pArr->Head = (int*)malloc(sizeof(int)*pArr->Cap);
	pArr->Num = 0;  //以后每次添加都加一,Num++
}
//参数:一个是结构体指针,一个是要添加的数据
void Add(struct DynamicArr * pArr, int AddNum)  
{
//判断是否装满
	if (pArr->Cap == pArr->Num )
	{
//容量变大 一定是先增加空间,再malloc,,不然还是不变
		pArr->Cap += 10; 	//装满就再申请空间
//申请中间指针变量装这个空间
		int *ptemp = (int*)malloc(sizeof(int)*pArr->Cap);
//将原数据复制新空间
		for (unsigned int i = 0; i < pArr->Num ; i++)
		{
			ptemp[i] = pArr->Head[i];
		}
//释放原空间
		free(pArr->Head );
//将数组头指针指向新空间
		pArr->Head = ptemp;
	}
//Head[pArr->Num]是指向最后一个元素   将新数据装入最后
	pArr->Head[pArr->Num] = AddNum;
	pArr->Num++;//累加元素的数量
}
int main(void)
{
	struct DynamicArr Arr;
	iniArr(&Arr);
	//调用  
	Add(&Arr, 3);
	Add(&Arr, 3);
	Add(&Arr, 3);
	Add(&Arr, 3);
	Add(&Arr, 3);
	Add(&Arr, 3);
	//这里可以封装函数
	printf("%u,%u\n",Arr.Cap ,Arr.Num );
	for (int i = 0; i < Arr.Num;i++)
		printf("%d ",Arr.Head [i]); //输出数组中的元素
	free(Arr.Head);
	system("pause");
	return 0;
}

输出封装

//输出封装
void print(struct DynamicArr *Arr)
{
	if (NULL == Arr) //判断是否为NULL,是就返回
	{
		printf("输出错误\n");
		return;
	}
	printf("%u,%u\n", Arr->Cap, Arr->Num);
	for (int i = 0; i < Arr->Num; i++)
	{
		printf("%d ", Arr->Head[i]); //输出数组中的元素
	}
}
//主函数调用
print(&Arr);
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沐鑫本鑫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值