可变数组及链表

文件目录

可变数组

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);
			}	
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值