c语言用数组初始化链表,C语言-可变数组、链表

这篇博客介绍了C语言中实现可变数组的两种方式:一种是通过结构体封装不可变数组,包括创建、释放、获取大小和元素等操作;另一种是采用链表实现可变数组,避免了频繁的内存分配问题。文中详细阐述了链表节点的定义、添加节点以及删除节点的方法,并讨论了静态本地变量的作用。此外,还提到了头文件、静态函数和全局变量的使用规范。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(整理自 中国大学幕课 浙江大学-C语言程序设计)

-可变数组

C语言的可变数组是由不可变数组封装起来的

首先构建一个结构体:

typedef struct {

int *array;

int size;

}Array;

Array即可变数组 实际上为一个结构体

array为一个地址 size为数组的大小

这个结构体加上几个函数 就构成了可变数组

函数包含:

Array array_create( int

init_size ) ;//创建数组结构体 初始化array和size

void array_free( Array

*a ) ;//释放数组内存

int array_size( const

Array *a ) ;//设置结构体中的size

int *array_at( Array

*a, int index );//先判断是否越界 若越界 则调用inflate函数,获取结构体中array[ index

]的元素

void array_inflate(

Array *a, int more_size );//给数组扩展空间

每次扩展一个块block

其中最后的函数 void array_inflate( Array *a, int

more_size ); 为数组扩展函数,用到了block,block为开辟空间大小块 避免一次开一个小空间而多次开辟

-链表

可变数组 不断创建内存

十分麻烦,而且在不断创建和释放的情况下 到后面会发生申请不到空间的情况,实际内存足够

但刚申请的数组内存的“后面”没有足够的内存

上面的方法生成数组

不适应所有情况,现在需要的是 不再copy原数组 而是在原数组的基础上

开辟一块内存,并将新开辟的内存链接到原数组后面,这样每次数组扩展时都不用自我复制并申请新的内存 可以避免申请不到空间的情况

将新的数组指向原来的数组:

“数据加指针”(即节点)该指针指向下一个“数据加指针”(即节点),最后一个单元用特殊符号表示结束(最后一个节点的指针为NULL)

用特殊指针指向第一个单元(head)

这一系列构成链表 每个单元叫节点

每一个节点是数据加指针

节点实际上是结构体 用typedef

声明,分别是int和指向下一个结构体的指针

typedef struct

_node{

int value ;

struct_node *next;

} Node ;

新添加的struct 是链表最后的节点

它的指针应该是NULL,然后将上一个节点的指针指向该新增的节点

特殊情况:第一个节点的判断

Node* n =

( Node*)malloc(sizeof (

Node ) ) ;

n ->value = i

;

n ->next = head

;

head = n ;

将以上过程封装成一个函数 即添加一定大小的链表

该函数需要传入参数head,而该参数是形参 在函数内部改变后外部仍然没有变化,最好不要将head全局化

因为可能需要多个链表,直接将head return传出去 则需要程序员调用该函数时用一个新的head接收它,未避免忘记接收的情况

我们在给函数传入head时就不要直接传形参 而是传head的指针,由于head本身就是一个指针

所以传入的参数是指针的指针(Node**),这样处理后 我们可以直接在函数内部对head进行需要的修改;第四个办法

函数中传入的是一个结构体(List)的指针,该结构体里面只有一个指针head,或者 上述函数添加链表都是从第一个head开始

我们可以在结构体list里面再添加一个指针(tail)该指针指向链表的最后一个节点

这样每次添加节点都可以直接用这个指针指向下一个新的节点

typedef struct{

Node* head ;

}List ;

void add_head ( List*

list , int i ) ;

利用for循环 建立链表

for ( p = head ; p ; p

= p ->next ){};

移除某节点

先将该节点的上节点的指针指向下节点,再移除该节点

for ( q = 0, p = head;

p; q = p, p = p->next ) {

if ( p->value == i )

{

q->next = p ->next;

}

}

-附:

静态本地变量即全局变量

静态本地变量具有全局的生存期,函数内的局部作用域

返回本地变量的地址是危险的

而返回全局变量或静态本地变量地址是安全的

头文件:把函数原型放到一个头文件(以.h结尾)中,在需要调用这个函数的源代码文件(.c文件)中

#include这个头文件,就能让编译器在编译的时候知道函数的原型,这样可以保证传入的参数类型与函数要求的一致,头文件形成一个桥梁

#include是一个预编译处理

指出要插入的文件,不是用来引入库的

而是把引号或括号中的文件里的内容插入到include这一行

在使用和定义这个函数的地方都应该#include这个头文件

在函数前面加上static就使得它成为只能在所在的编译单元中被使用的函数,在全局变量前面加上static就使得它成为只能在所在的编译单元中被使用的全局变量

% [flag] [width]

[.prec] [hlL] type

C语言中的MVC模式

view和control没有直接发生联系,control通过改变model 从而改变view

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值