数组的理解与实现[数据结构]
2016-01-26 12:40
639 查看
一、概述
相信大家对数组都不会太陌生,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位置的元素都得向后移动,非常耗时间。
所以,总结优缺点:
优点:查找快速、相对链表占用空间少
缺点:插入、删除很慢,并且需要连续的大块空间来存储数据。
以上就是关于数组的简单讲解,本人也是初学,很多问题不甚明了,讲解的不够透彻。
如有错误之处,敬请不吝指正。
如有不明之处,欢迎相互探讨。
相关文章推荐
- C#数据结构之顺序表(SeqList)实例详解
- Lua教程(七):数据结构详解
- 解析从源码分析常见的基于Array的数据结构动态扩容机制的详解
- C#数据结构之队列(Quene)实例详解
- C#数据结构揭秘一
- C#数据结构之单链表(LinkList)实例详解
- 数据结构之Treap详解
- C#数据结构之堆栈(Stack)实例详解
- C#数据结构之双向链表(DbLinkList)实例详解
- JavaScript数据结构和算法之图和图算法
- Java数据结构及算法实例:冒泡排序 Bubble Sort
- Java数据结构及算法实例:插入排序 Insertion Sort
- Java数据结构及算法实例:考拉兹猜想 Collatz Conjecture
- java数据结构之java实现栈
- java数据结构之实现双向链表的示例
- Java数据结构及算法实例:选择排序 Selection Sort
- Java数据结构及算法实例:朴素字符匹配 Brute Force
- Java数据结构及算法实例:汉诺塔问题 Hanoi
- Java数据结构及算法实例:快速计算二进制数中1的个数(Fast Bit Counting)
- java数据结构和算法学习之汉诺塔示例