【算法】C语言实现数组的动态分配
C语言实现数组的动态分配
作者:白宁超
2016年10月27日20:13:13
摘要:数据结构和算法对于编程的意义不言而喻,具有指导意义的。无论从事算法优化方向研究,还是大数据处理,亦或者网站开发APP开发云云。在求职过程中数据结构必然也是笔试的重点,面试的常客。基于此,系统梳理复习下数据结构和算法相关知识,其实核心为链表操作,串的匹配,树的先序、中序、后序。排序的相关操作,查找相关操作,深度优先遍历、广度优先遍历、哈弗曼树、动态规划等。本节为开胃菜,数组的相关操作(本文原创编著,转载注明出处:C语言实现数组的动态分配)
1 数组动态分配思想
数组是最常用的数据结构,在内存中连续存储,可以静态初始化(int a[2]={1,2}),可以动态初始化 malloc()。难点就是数组在删除或者插入元素的时候,要移动元素的坐标不好确定。规律:
1.如果要在数组中第pos个位置插入一个元素(应该从后面开始移动)
for( i=cnu;i>=pos;i--)
pBase[i]=pBase[i-1];
2.删除数组第pos位置的元素
for(i=pos+1;i<=cnu;i--)
pBase[i-2]=pBase[i-1];
使用malloc动态分配内存并将返回值赋给整形指针
int pBase=(int *)malloc(sizeof(int)len);//分配4*len字节长度的内存
这是pBase可以指向数组中的第一个元素,可以作为数组变量名称使用。
2 数组的优缺点
优点:
存取速度快 o(1) 可以直接根据下标找到内存位置
缺点:
- 事先必须知道数组的长度
- 插入删除元素很慢
- 空间通常是有限制的
- 需要大块连续的内存块
- 插入删除元素的效率很低
3 完整案例
#include<stdio.h>
#include<malloc.h>
#include<stdbool.h> /* 定义结构体 */
struct Arr{
int len;//数组能存取的最大元素个数
int cnu;//数组中当前元素个数
int *pBase;//存储指向数组的指针
}; /*初始化数组*/
void init_Arr(struct Arr *pArray,int len){
pArray->pBase=(int*)malloc(sizeof(int)*len);//分配4*len字节长度的内存
if(NULL== pArray->pBase){
printf("动态分配内存失败\n");
}else{
pArray->len=len;
pArray->cnu=0;
printf("动态分配内存成功 %d \n",pArray->len);
}
} /*判断数组是否为空,传地址省内存4字节,传结构体变量需要进行拷贝,12字节*/
bool isempty(struct Arr *pArray){
if(0==pArray->cnu) return true;
else return false;
} /*判断数组是否满了*/
bool isfull(struct Arr *pArray){
if(pArray->len==pArray->cnu) return true;
else return false;
}
/*显示数组内容*/
void show_Arr(struct Arr *pArray){
if(isempty(pArray)) printf("数组为空!\n");
else{
for(int i=0; i<pArray->cnu;i++){
printf("%d \t\t %d \t\t %d \n",pArray->pBase[i],pArray->cnu,pArray->len);
}
printf("------------------------------------\n");
}
} /*向数组追加元素*/
bool append(struct Arr *pArray,int val){
if(isfull(pArray)){
printf("数组已经满了!\n");
return false;
}else{
pArray->pBase[pArray->cnu]=val;
pArray->cnu++;
}
} /*向数组中插入元素,pos为数组中第几个位置,pos=3就是向a[2]插入元素*/
bool insert(struct Arr *pArray,int pos,int val){
if(pos<1||pos>pArray->len+1){
printf("插入的位置输入的不合法\n");
return false;
}
if(isfull(pArray)){
printf("数组已经满了,插入失败!\n");
return false;
}
else{
//printf("数组 %d \n",pArray->cnu);
for(int i=pArray->cnu;i>=pos;i--){//循环将pos位置开始的数组后移
pArray->pBase[i]=pArray->pBase[i-1];
}
pArray->pBase[pos-1]=val;
pArray->cnu++;
pArray->len++;
return true;
}
} /*删除数组中的第pos个元素,同时返回删除的元素的值*/
bool delete(struct Arr *pArray,int pos,int *val){
if(pos<1||pos>pArray->cnu){
printf("删除失败,位置不合法\n");
return false;
}
if(isempty(pArray)){
printf("数组已经空,删除失败!\n");
return false;
}
else{
*val=pArray->pBase[pos-1];
for(int i=pos+1;i<=pArray->cnu;i++){
pArray->pBase[i-2]=pArray->pBase[i-1];
}
pArray->cnu--;
return true;
}
}
/*数组倒置*/
bool inverse(struct Arr *pArray){
if(isempty(pArray)){
printf("倒置失败,因数组为空");
return false;
}
else{
int i=0,j=pArray->cnu-1,temp;
while(i<j){
temp=pArray->pBase[i];
pArray->pBase[i]=pArray->pBase[j];
pArray->pBase[j]=temp;
i++;
j--;
}
}
return true;
} int main(){
struct Arr arr;
init_Arr(&arr,20);
append(&arr,1);
append(&arr,2);
append(&arr,3);
append(&arr,4);
append(&arr,5);
show_Arr(&arr);
insert(&arr,2,88);
show_Arr(&arr);
int val;
delete(&arr,1,&val);
show_Arr(&arr);
printf("删除了 %d\n",val);
inverse(&arr);
show_Arr(&arr);
return 0;
}
4 运行结果
Success time: 0 memory: 2300 signal:0
动态分配内存成功 20
1 5 20
2 5 20
3 5 20
4 5 20
5 5 20
------------------------------------
1 6 21
88 6 21
2 6 21
3 6 21
4 6 21
5 6 21
------------------------------------
88 5 21
2 5 21
3 5 21
4 5 21
5 5 21
------------------------------------
删除了 1
5 5 21
4 5 21
3 5 21
2 5 21
88 5 21
------------------------------------
5 实例解析
结构体:结构体(struct)指的是一种数据结构,是C语言中聚合数据类型的一类。 结构体可以被声明为变量、指针或数组等,用以实现较复杂的数据结构。结构体的定义如下所示,
struct tag { member-list } variable-list ;
struct为结构体关键字,tag为结构体的标志,member-list为结构体成员列表,其必须列出其所有成员;variable-list为此结构体声明的变量。
思路:
- 创建结构体记得关键字struct
- 花括号内创建结构体属性
例如:
/* 定义结构体 */
struct Arr{
int len;//数组能存取的最大元素个数
int cnu;//数组中当前元素个数
int *pBase;//存储指向数组的指针
};
初始化数组:
思路:
- 创建初始化函数,给数组分配长度malloc(sizeof(int)*len
- 指针地址为空,分配内存失败
- 反之,数组长度为当前内存长度,数组当前位置为0
例如:
/*初始化数组*/
void init_Arr(struct Arr *pArray,int len){
pArray->pBase=(int*)malloc(sizeof(int)*len);//分配4*len字节长度的内存
if(NULL== pArray->pBase){
printf("动态分配内存失败\n");
}else{
pArray->len=len;
pArray->cnu=0;
printf("动态分配内存成功 %d \n",pArray->len);
}
}
判断数组是否为空:
- 创建判空函数,结构体参数数组
- 判断当前元素个数是否为空
/*判断数组是否为空,传地址省内存4字节,传结构体变量需要进行拷贝,12字节*/
bool isempty(struct Arr *pArray){
if(0==pArray->cnu) return true;
else return false;
}
判断数组是否为满:
- 创建判满函数,结构体参数数组
- 判断数组长度是否为当前元素长度
例如:
/*判断数组是否满了*/
bool isfull(struct Arr *pArray){
if(pArray->len==pArray->cnu) return true;
else return false;
}
向数组追加元素:
- 创建追加函数,结构体数组参数,元素值
- 注意判满情况,反之循环输入
- 数组当前指针地址赋值
- 数组指向下一个位置,自加
例如:
/*向数组追加元素*/
bool append(struct Arr *pArray,int val){
if(isfull(pArray)){
printf("数组已经满了!\n");
return false;
}else{
pArray->pBase[pArray->cnu]=val;
pArray->cnu++;
}
}
显示数组内容
- 创建显示函数,结构体数组参数
- 注意判空情况,反之循环输入
- 遍历数组输出
例如:
/*显示数组内容*/
void show_Arr(struct Arr *pArray){
if(isempty(pArray)) printf("数组为空!\n");
else{
for(int i=0; i<pArray->cnu;i++){
printf("%d \t\t %d \t\t %d \n",pArray->pBase[i],pArray->cnu,pArray->len);
}
printf("------------------------------------\n");
}
}
向数组中插入元素:pos为数组中第几个位置,pos=3就是向a[2]插入元素
- 创建插入函数,结构体数组参数,位置参数,插入值参数
- 判断插入位置是否越界,判断数组是否满
- 循环将pos位置开始的数组后移,移动范围是从第pos个到第cnu个
- 循环将pos位置开始的数组后移,将值插入pos处
- 指向下一位且长度加1
例如:
/*向数组中插入元素,pos为数组中第几个位置,pos=3就是向a[2]插入元素*/
bool insert(struct Arr *pArray,int pos,int val){
if(pos<1||pos>pArray->len+1){
printf("插入的位置输入的不合法\n");
return false;
}
if(isfull(pArray)){
printf("数组已经满了,插入失败!\n");
return false;
}
else{
//printf("数组 %d \n",pArray->cnu);
for(int i=pArray->cnu;i>=pos;i--){//循环将pos位置开始的数组后移
pArray->pBase[i]=pArray->pBase[i-1];
}
pArray->pBase[pos-1]=val;
pArray->cnu++;
pArray->len++;
return true;
}
}
删除数组中的第pos个元素:同时返回删除的元素的值
- 创建插入函数,结构体数组参数,位置参数,插入值参数
- 判断插入位置是否越界合法
- 获取删除的元素值
- 移动单位是从第pos+1个到cnu
- 指针向前指向,自减
例如:
/*删除数组中的第pos个元素,同时返回删除的元素的值*/
bool delete(struct Arr *pArray,int pos,int *val){
if(pos<1||pos>pArray->cnu){
printf("删除失败,位置不合法\n");
return false;
}
if(isempty(pArray)){
printf("数组已经空,删除失败!\n");
return false;
}
else{
*val=pArray->pBase[pos-1];
for(int i=pos+1;i<=pArray->cnu;i++){
pArray->pBase[i-2]=pArray->pBase[i-1];
}
pArray->cnu--;
return true;
}
}
数组倒置
- 创建倒置函数,判断数组是否为空
- 三个变量进行交换,其中temp中间变量,ij分别指向数组首尾索引
- 循环数组,使前后索引交换位置
- 每一遍循环,ij索引分别前进一步,直到跳出循环,程序结束
例如:
/*数组倒置*/
bool inverse(struct Arr *pArray){
if(isempty(pArray)){
printf("倒置失败,因数组为空");
return false;
}
else{
int i=0,j=pArray->cnu-1,temp;
while(i<j){
temp=pArray->pBase[i];
pArray->pBase[i]=pArray->pBase[j];
pArray->pBase[j]=temp;
i++;
j--;
}
}
return true;
}
【算法】C语言实现数组的动态分配的更多相关文章
- C语言学习笔记之动态分配数组空间
本文为原创文章,转载请标明出处 高级语言写多了,再拿起C语言的时候,自己已经傻了... C语言中数组大小不能为变量,即使这个变量已经被赋过值了,应该使用malloc方法进行数组空间动态分配. 如下: ...
- C++内存分配及变长数组的动态分配
//------------------------------------------------------------------------------------------------ 第 ...
- 学习C语言的数组
C语言的数组 数组声明的实例:int num[3];只要记下这个模板就好. 不建议使用变量定义数组,如果使用了变量定义数组,作为数组的元素的个数,不初始化的情况下是随机值,如果初始化会直接报错 注意: ...
- Java数据结构和算法(二)——数组
上篇博客我们简单介绍了数据结构和算法的概念,对此模糊很正常,后面会慢慢通过具体的实例来介绍.本篇博客我们介绍数据结构的鼻祖——数组,可以说数组几乎能表示一切的数据结构,在每一门编程语言中,数组都是重要 ...
- 坐标轴刻度取值算法-基于魔数数组-源于echarts的y轴刻度计算需求
本文链接:https://blog.csdn.net/qq_26909801/article/details/96966372数值型坐标轴刻度计算算法前言算法描述上代码代码运行效果结语前言因实习的公司 ...
- C语言一维数组、二维数组、结构体的初始化
C语言数组的初始化表示方法 一.C语言一维数组初始化: (1)在定义数组时对数组元素赋以初值.如: static int a[10]={0,1,2,3,4,5,6,7,8,9}; 经过上面的定义和初始 ...
- go语言的 数组、slice、map使用(转)
golang群 点击加入 go语言的 数组.slice.map使用, 由于网上有很好的说明, 不需要再写了,请看这几篇: Go语言中的 Array, Slice和 Map 深入学习golang五篇,以 ...
- go语言 类型:数组
在go语言中数组array是一组特定长度的有序的元素集合. go的数组类型由两部分组成——类型和长度,二者缺一不可.数组本来就是一块存储相同类型元素的连续内存空间,因此决定一个数组的类型,必然需要决定 ...
- C语言基础--数组及相关
概念: 一堆相同类型的数据的有序集合 格式: 元素类型 数组名称[ 元素个数 ] 定义数组: // 定义了一个名称叫做scores的数组, 数组中可以存放3个int类型的数据 ]; // 只要定义一 ...
随机推荐
- NPM (node package manager) 入门 - 基础使用
什么是npm ? npm 是 nodejs 的包管理和分发工具.它可以让 javascript 开发者能够更加轻松的共享代码和共用代码片段,并且通过 npm 管理你分享的代码也很方便快捷和简单. 截至 ...
- HTTP协议系列(1)
一.为什么学习Http协议 首先明白我们为什么学习HTTP协议,也就是说明白HTTP协议的作用.HTTP协议是用于客户端与服务器之间的通讯.明白了HTTP协议的作用也就知道了为什么要学习H ...
- 支持 .NET Core 的 Memcached 客户端 EnyimMemcachedCore
1. 介绍 EnyimMemcachedCore 是一个支持 .NET Core 的 Memcached 客户端,是从 EnyimMemcached 迁移至 .NET Core的,源代码托管在 Git ...
- ASP.NET Core 折腾笔记一
前言: 在ASP.NET Core 1.0时,曾折腾过一次,后因发现不了System.Data而停止. 更因VS2015提示过期Delete掉VS了,其实主要还是笔记本的硬盘空间吃紧. 快双十一了,本 ...
- Jvm 内存浅析 及 GC个人学习总结
从诞生至今,20多年过去,Java至今仍是使用最为广泛的语言.这仰赖于Java提供的各种技术和特性,让开发人员能优雅的编写高效的程序.今天我们就来说说Java的一项基本但非常重要的技术内存管理 了解C ...
- 浅谈Slick(2)- Slick101:第一个动手尝试的项目
看完Slick官方网站上关于Slick3.1.1技术文档后决定开始动手建一个项目来尝试一下Slick功能的具体使用方法.我把这个过程中的一些了解和想法记录下来和大家一起分享.首先我用IntelliJ- ...
- Hibernate 系列 学习笔记 目录 (持续更新...)
前言: 最近也在学习Hibernate,遇到的问题差不多都解决了,顺便把学习过程遇到的问题和查找的资料文档都整理了一下分享出来,也算是能帮助更多的朋友们了. 最开始使用的是经典的MyEclipse,后 ...
- NOT IN 和NOT EXISTS
今天写了一个简单的NOT IN语句,结果跟预期大相径庭,百度之发现深坑一个,遂录之. 登陆账户表logins code name status a admin N b guest N c member ...
- Ubuntu手动设置DSL连接
在安装完Ubuntu之后,发现图形界面的DSL连接不管用了,郁闷了好几天,想想移动每个月120个小时的流量岂不是白白浪费了.正当我想重返Windows系统的时候,却发现了手动设置连接DSL的好方法,感 ...
- oracle常用的快捷键
最近在开发过程中,遇到一些麻烦,就是开发效率问题,有时候其他同事使用PLSQL 编程效率明显高于自己,观察了好久,才发现他使用PLSQL 已经很长时间了而且,他自己也在其中添加了好多快捷方式, 1.登 ...