数组的理解与实现[数据结构]

一、概述

相信大家对数组都不会太陌生,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位置的元素都得向后移动,非常耗时间。

所以,总结优缺点:

优点:查找快速、相对链表占用空间少

缺点:插入、删除很慢,并且需要连续的大块空间来存储数据。

以上就是关于数组的简单讲解,本人也是初学,很多问题不甚明了,讲解的不够透彻。
如有错误之处,敬请不吝指正。
如有不明之处,欢迎相互探讨。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值