一、概述
相信大家对数组都不会太陌生,C、C++、Java、PHP等高级语言中,都有数组这个概念。
数组是一种线性结构,也属于比较简单的一种结构。但是简单的东西往往意味着使用广泛。
数组在各大语言中都有所涉及,是很重要的一种数据结构。
掌握数组,可以使我们对编程有另一个角度的理解,有助于我们合理的使用数组,使代码“更上一层楼”。
下面,我们就用C语言来实现数组吧!
二、数组的实现
建议:程序用到了C语言中“指针“、”结构体“、”malloc()“的知识,请先学习这部分知识,否则下面代码看起来很晕。。。
1、首先,我们先将能够表示数组的结构建立出来
typedef struct Arr
{
int length; //数组长度
int *pBase; //指向数组第1个元素的指针
int cnt; //数组的有效长度
}ARR,*PARR; //PARR为指向变量ARR类型的指针
程序意义如下图:
2、我们初始化一个数组
//初始化数组
void initArr(PARR pArr,int length)
{
pArr->pBase=(int *)malloc(sizeof(int)*length);
if(pArr->pBase==NULL)
{
printf("数组初始化失败\n");
exit(-1);
}
else
{
pArr->length=length;
pArr->cnt=0;
}
}
如果初始化成功,会如下图(我们假设length=3):
3、在末尾追加元素
//追加元素,int val为插入的值
void appendArr(PARR pArr,int val)
{
if(isFull(pArr))//isFull()是判断数组是否已满的函数,这里先不用管
{
printf("数组已满。不可追加元素!\n");
}
else
{
pArr->pBase[pArr->cnt]=val;
pArr->cnt++;
}
}
假设我们调用此函数,追加2和4到数组。如下图:
4、在任意位置插入一个元素
//插入元素,val为要插入的值,pos为插入的位置
void insertArr(PARR pArr,int val,int pos)
{
if(isFull(pArr))
{
printf("数组已满,不可插入元素\n");
}
else
{
int i;
for(i=pArr->cnt;i>=pos;i--)
{
pArr->pBase[i]=pArr->pBase[i-1];
}
pArr->pBase[pos-1]=val;
pArr->cnt++;
}
}
比如:我在 1 位置插入 数值 6,那么就像下图了:
for(i=pArr->cnt;i>=pos;i--)
{
pArr->pBase[i]=pArr->pBase[i-1];
}
上面这段代码可能不太好理解,以上面数组为例讲解
未插入元素前,数组含有元素2、4,数组的cnt(有效长度)位2。
要想插入元素,那么2、4元素都要向后移动一个位置,
当然先从4开始移动(从2开始移动的话,2会覆盖掉4)
上面代码就是说,先从最后一位(4)开始向后依次移动,空出第1个位置来。
如图:
5、遍历数组
//遍历数组
void showArr(PARR pArr)
{
if(isEmpty(pArr))
{
printf("数组为空!\n");
}
else
{
int i;
for(i=0;i<pArr->cnt;i++)
{
printf("%d ",pArr->pBase[i]);
}
}
}
遍历数组比较简单,这里就不详细讲解了,但要注意:
*(a+i)==a[i](a是指向数组 起始位置的指针)相当于这里的
*(pArr->pBase + i)==pArr->pBase[i]
6、删除任意位置的元素
//删除任意位置的元素
void deleteArr(PARR pArr,int pos)
{
if(isEmpty(pArr))
{
printf("数组为空,不可删除\n");
}
else
{
int i;
for(i=pos;i<pArr->cnt;i++)
{
pArr->pBase[i-1]=pArr->pBase[i];
}
pArr->cnt--;
}
}
上面的核心代码为:
for(i=pos;i<pArr->cnt;i++)
{
pArr->pBase[i-1]=pArr->pBase[i];
}
以以上数组讲解此代码:
数组原有3个元素6、2、4,假设我们要删除第1个位置的元素
那么,2就向前移动一个位置(2→覆盖→6),
接下来,4再向前移动一个位置(4→覆盖→2)。
上面代码就是实现了覆盖的一个功能,如图:
三、总体实现代码
#include <stdio.h>
#include <stdlib.h>
typedef struct Arr
{
int length; //数组长度
int *pBase; //指向数组第1个元素的指针
int cnt; //数组的有效长度
}ARR,*PARR; //PARR为指向变量ARR类型的指针
//初始化数组
void initArr(PARR pArr,int length)
{
pArr->pBase=(int *)malloc(sizeof(int)*length);
if(pArr->pBase==NULL)
{
printf("数组初始化失败\n");
exit(-1);
}
else
{
pArr->length=length;
pArr->cnt=0;
}
}
//判断数组是否已满
int isFull(PARR pArr)
{
if(pArr->length==pArr->cnt)
{
return 1;
}
else
{
return 0;
}
}
//追加元素
void appendArr(PARR pArr,int val)
{
if(isFull(pArr))
{
printf("数组已满。不可追加元素!\n");
}
else
{
pArr->pBase[pArr->cnt]=val;
pArr->cnt++;
}
}
//插入元素
void insertArr(PARR pArr,int val,int pos)
{
if(isFull(pArr))
{
printf("数组已满,不可插入元素\n");
}
else
{
int i;
for(i=pArr->cnt;i>=pos;i--)
{
pArr->pBase[i]=pArr->pBase[i-1];
}
pArr->pBase[pos-1]=val;
pArr->cnt++;
}
}
//判断数组是否为空
int isEmpty(PARR pArr)
{
if(pArr->cnt==0)
{
return 1;
}
else
{
return 0;
}
}
//遍历数组
void showArr(PARR pArr)
{
if(isEmpty(pArr))
{
printf("数组为空!\n");
}
else
{
int i;
for(i=0;i<pArr->cnt;i++)
{
printf("%d ",pArr->pBase[i]);
}
}
}
//删除任意位置的元素
void deleteArr(PARR pArr,int pos)
{
if(isEmpty(pArr))
{
printf("数组为空,不可删除\n");
}
else
{
int i;
for(i=pos;i<pArr->cnt;i++)
{
pArr->pBase[i-1]=pArr->pBase[i];
}
pArr->cnt--;
}
}
//主函数
int main()
{
ARR arr;
int length=3;
initArr(&arr,length);
appendArr(&arr,2);
appendArr(&arr,4);
insertArr(&arr,6,1);
deleteArr(&arr,1);
showArr(&arr);
return 0;
}
四、数组的优缺点
由以上对数组的实现可知:
数组的遍历、以及取出某个位置的元素非常快,因为数组是连续的
但是要想在任意位置 插入、删除 元素确很慢,需要大动干戈。
比如数组一共有10个位置,现在要在2位置插入一个元素,那么3-9位置的元素都得向后移动,非常耗时间。
所以,总结优缺点:
优点:查找快速、相对链表占用空间少
缺点:插入、删除很慢,并且需要连续的大块空间来存储数据。
以上就是关于数组的简单讲解,本人也是初学,很多问题不甚明了,讲解的不够透彻。
如有错误之处,敬请不吝指正。
如有不明之处,欢迎相互探讨。