今天学习了中国大学mooc上翁恺老师《C语言程序设计》的第14课链表。在学习链表之前,老师讲解了普通的可变数组的实现。
前奏:可变数组的实现(有缺陷)
首先定义一个结构体,内部存在一个指针和存放大小的变量
typedef struct{ int *array; int size; }Array;
其次明确目标,对数组所需的操作有:创建 丶清除(释放内存) 丶显示大小 丶访问和赋值 丶扩大这几个功能
函数申明如下:
#define BLOCK 20
Array array_create(int init_size);
void array_free(Array *a);
int array_size(const Array *a);
int *array_at(Array *a,int index);
void array_inflate(Array *a,int more_size);
1.创建
Array array_create(int init_size)
{
Array a;
a.size = init_size;
a.array = (int*)malloc(sizeof(int)*a.size);//开辟一块新的空间
return a;
}
2.清除
这一部分比较简单
void array_free(Array *a)
{
free(a->array);
a->array = NULL;
a->size = 0;
}
3.显示大小
int array_size(const Array *a){
return a->size;
}
4.访问和赋值
int *array_at(Array *a,int index)
{
if(a->size<=index)
array_inflate(a,(index/BLOCK+1)*BLOCK-a->size);
return &(a->array[index]);
}//返回指针是为了 能对值加以修改
思考一下,为什么采用返回指针呢?返回int不是更香嘛?
事实上,我们不仅要访问,还要对值进行修改,只有取得变量的地址才能进行操作。
例如:*array_at(&a,1000) = 101;
5.数组的扩大(核心)
这是区别去其他数组的地方
事实上malloc申请的内存是不可变的,于是我们智能通过申请一块新的内存对原先的进行覆盖。
void array_inflate(Array *a,int more_size)//放大原理,制造一片新的空间
{
int* p = (int*)malloc(sizeof(int)*(more_size+a->size));
int i;
for(i=0;i<a->size;i++)
p[i] = a->array[i];
free(a->array);
a->array = p;
a->size+=more_size;
}
在这里定义了一个BLOCK 恒为20.
学习过程中,发现自己忘记了.和->的区别,多次编译出错.经过百度后知道:
结构体用点,结构体指针用箭头。(*p).member等价于p->member
注意:这样的可变数组是有缺陷的:1.当数目较大时,每次开辟内存所占空间较大 2.当内存有限制时,可能无法申请到内存
需要用链表。