可变数组
C的数组一旦定义后无法改变,所以自己来实现一个可以变大小的数组
特点:可以长大 现在有多大 访问当中的单元
实现一个函数库,定义以下函数
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);让数组长大
array.h
#ifndef _ARRAY_H_
#define _ARRAY_H_
typedef struct {
int *array;
int size;
} Array;
Array array_create(int init_szie);
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);
#endif
具体操作:
参数为size
Array array_create(int init_size)
{
Array a;
a.size = init_size;
a.array = (int*)malloc(sizeof(int)*a.size);
return a; //返回Array变量本身
}
释放空间
void array_free(Array *a)
{
free(a->array);
a->array = NULL;
a->size = 0; //free 0 、free NULL是无害的 保证其内容清0;
}
数组中有多少单元可以用
//封装
int array_size(const Array *a) //现在数组有多少个单元
{
return a->size; //将a->size保护起来了
}
进行可读可写的操作
定义增长量为一个block
const BLOCK_SIZE = 20;
int* array_at(Array *a, int index)
{
if (index >= a->size){
array_inflate(index/BLOCK_SIZE+1)*BLOCK_SIZE-a->size);
}
return &(a->array[index]); //返回指针
}
自动增长
void array_inflate(Array *a,int more_size)
{
int *p = (int*)malloc(sizeof(int)*(a->size + more_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; //核心代码
}
实现函数功能
int main(int argc, char const *argv[])
{
Array a= array_create(100); //a本身在离开main时空间会被回收,a本身是一个本地变量
printf("%d\n",array_size(&a));
*array_at(&a, 0) = 10; //可将一个值写入数组中
printf("%d\n", *array_at(&a,0));
int number;
int cnt = 0;
while( number != -1){
scanf("%d", &number);
if ( number != -1)
*array_at(&a, cnt++) = number;
}//实现当number=-1时退出,不等于-1时记录这个数
array_free(&a);
return 0;
}
此种方法弱点:
1、每次长大的都需要去申请新的内存空间可以容纳全部的东西
2、拷贝要花费时间
3、明明有足够的内存,再也不能申请空间了
4、不高效
链表
自定义可变数组的解决办法:申请一块block大的内存,将它们链起来
结点包括:数据和指向下一个的指针
结点定义:将其定义为一个结构
#ifndef _NODE_H_
#define _NODE_H_
typedef struct _node {
int value;
struct _node *next; //指向它自己
}Node;
#endif
故事背景:程序需要读到很多的number;读到-1停止
1、在链表中加一个新的元素
int main(int argc, char const *argv[])
{
Node * head = NULL; //有一个Node的指针为head,
int number;
do {
scanf("%d", &number);
if (number != -1){
//add to linked-list 每读一个数做一个Node的结构体
Node *p = (Node*)malloc(sizeof(Node)); //有一个指针以malloc方式得到
p->value = number;
p->next = NULL; //对p所指东西进行初始化
// find the last
Node *last = head;
if ( last ){
while (last->next){
last = last->next;
}
//attch
last->next = p;
}else {
head = p;
}
}
}while (number != -1);
return 0;
}
2、用自己定义的结构List来代表整个链表
typedef struct _list{
Node* head;
} List;
void add(Node* head, int number);
int main(int argc, char const *argv[])
{
// Node * head = NULL; //有一个Node的指针为head,
List list; //建立一个是List的结构体为list;
int number;
list.head = NULL;
do {
scanf("%d", &number);
if (number != -1){
head = add(&list, number );
}
}while (number != -1);
return 0;
}
void add(List* pList, int number)
{
//add to linked-list 每读一个数做一个Node的结构体
Node *p = (Node*)malloc(sizeof(Node)); //有一个指针以malloc方式得到
p->value = number;
p->next = NULL; //对p所指东西进行初始化
// find the last
Node *last = PList->head;
if ( last ){
while (last->next){
last = last->next;
}
//attch
last->next = p;
}else {
pList->head = p;
}
}
3、链表搜索
for ( p=lsit.head; p; p=p->next){
if ( p->value == number){
printf("找到了");
isFound=1;
break;
}
}
if ( !isFound){
printf("没找到");
}
4、链表删除
Node *q;
for ( q=NULL;p=lsit.head; p;q=p; p=p->next){
if ( p->value == number){
q->next = p->next;
free(p);
break;
}
}
5、链表清除
for ( p=head;p; p=q){
q = p->next;
free(p);
}