23-链表
可变数组
接口
- 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); 让数组长大
the Array
typedef struct{
int *array;
int size;
}Array;
array _creat()
Array array _create(int init_size)
{
Array a;
a.size = init_size;
a.array = (int*)malloc(sizeof(int)*init_size);
return a;
}
array _free()
void array_free(Array *a)
{
free(a->array);
a->array = NULL;
a->size = 0;
}
array _size()
int array_size(const Array *a)
{
return a->size;
}
array _at() (封装作用)
int *array _at(Array *a , int index)
{
if(index>=a->size){ //有扩展功能
array_inflat(a,(index/BLOCK_SIZE+1)*BLOCK_SIZE-a->size); //此处BLOCK_SIZE是每次增加的常量
}
return &(a->array[index]);
}
此处有第二种访问方法:
用array_get() , array_set()
array _inflate()
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;
}
main()
int main(int argc,char const *argv[])
{
Array a = array_creat(100); //创建数组
printf("%d\n",array_size(&a)); //数组大小
*array_at(&a,0) = 10; //通过函数找到位置并解引用赋值
printf("%d",*array_at(&a,0));
int number = 0;
int cnt = 0;
while(number = -1){
scanf("%d",&number);
if(number!=-1){
*array_at(&a,cnt++) = number; //cnt++变化需要的空间大小,at函数有扩展作用
}
}
array_free(&a); //释放内存
return 0;
}
可变数组的缺陷
会遇到内存不够用,或无法在申请内存的情况,而且每次申请都需要拷贝,效率低,故需要用到链表。
链表
#include <stdio.h>
#include <stdlib.h>
typedef struct _node{ //定义结构
int value; //数据
struct _node *next; 连接下一个结构
}Node;
typedef struct _list{
Node *head;
}List;
void add(List *phead,int number);
void print(List *plist);
int main(int argc,char const *argv[])
{
List list;
list.head = NULL; //头指针放空
int number;
do{ //每次循环都需要从头开始
scanf("%d",&number);
if(number!=-1){
add(&list,number);
}
}while(number!=-1);
//搜索
printf("接下来是搜索:\n");
print(&list);
//链表的删除
scanf("%d\n",number);
Node *q;
Node *p;
int isFound = 0;
for(q = NULL,p = list.head ; p ; q=p,p = p->next ){
if(p->value == number){
q->next = p->next ;
}else{
list.head = p->next ; //找的数在开头的情况
}
free(p);
break ;
}
//链表的清除
for(p = list.head ;p ;p = q){
q = p->next ;
free(p);
}
return 0;
}
void add(List *plist,int number) //链表函数
{
Node *p = (Node*)malloc(sizeof(Node)); //指针p申请空间
p->value = number; //填入数字
p->next = NULL; //填入空
Node *last = plist->head;
if(last){ //找到空
while(last->next){ //last指向next的值是否为NULL来判断是否连接下一个结构
last = last->next; //由于原来位置有值last指向下一个结构
}
last->next = p; //由于last指向的next为空,在空结构写入*p值的结构(此时value中有数据,next中为NULL)
}else{
plist->head = p;
}
}
void print(List *plist){ //链表搜索
Node *p;
for(p = plist->head ; p ; p = p->next ){
printf("%d\t",p->value );
}
printf("\n");
}
链表函数
void add(List *plist,int number) //链表函数
{
Node *p = (Node*)malloc(sizeof(Node)); //指针p申请空间
p->value = number; //填入数字
p->next = NULL; //填入空
Node *last = plist->head;
if(last){ //找到空
while(last->next){ //last指向next的值是否为NULL来判断是否连接下一个结构
last = last->next; //由于原来位置有值last指向下一个结构
}
last->next = p; //由于last指向的next为空,在空结构写入*p值的结构(此时value中有数据,next中为NULL)
}else{
plist->head = p;
}
}
画图理解:
链表搜索
void print(List *plist){ //链表搜索
Node *p;
for(p = plist->head ; p ; p = p->next ){
printf("%d\t",p->value );
}
printf("\n");
}
链表删除
通过两个指针,直接从前一个结构连接到后一个结构跳过中间的数,来删除中间的数
scanf("%d\n",number);
Node *q;
Node *p;
int isFound = 0;
for(q = NULL,p = list.head ; p ; q=p,p = p->next ){
if(p->value == number){
q->next = p->next ;
}else{
list.head = p->next ; //找的数在开头的情况
}
free(p);
break ;
}
链表清除
for(p = list.head ;p ;p = q){
q = p->next ;
free(p);
}
此节有链表构成的一些过程看翁恺老师原视频:MOOC