C语言链表—理论篇

通常,程序开发最重要的部分是找到程序中表示数据的好方法。正确的表示数据可以更容易地编写程序其余部分。

以上这段话来自《C Prime Plus》第17章—高级数据表示。在工作中发现,许多有问题的程序,究其原因都是在设计之时缺乏对数据表示的深入的思考:一个不经意的变量使用,一个本可以复用却新写的函数,一个性能不佳但是可以快速实现的逻辑等等。

有时候我们感觉一个程序很烂,但是真要去改的时候却无从下手。恰好过去这一阵都在做代码的重构,大体的方法不难,但是我发现由于编程基本功的不扎实许多方法想不到。就像今天要记录的C语言链表。

注:以下示例摘自《C Prime Plus》第17章。

假如我们来编写一个程序,让用户输入一年内看过的所有电影。要存储每部电影的各种信息,如片名、发行年份、导演、主演、影片种类等等。建议使用一个结构存储每部电影,一个数组存储一年内看过的电影。为了简单起见,我们规定结构中只有两个成员:片名和等级(1~10)。

对于电影信息,可以采取结构数组的存储方式:

#define MAX_SIZE 5
#define MAX_NAME_LEN 50

struct film{
    char name[MAX_NAME_LEN];
    int rating;
};

int main(void){
    struct film movies[MAX_SIZE];
    ...
}

结构数组的弊端是数据表示不太灵活:电影数组的成员数量是固定的。相对灵活的方式为,程序在运行时确定所需内存量,可以通过动态内存分配来表示数据。

我们定义一个指向结构体的指针,通过malloc动态分配内存,由用户输入电影的最大数量,在程序的运行过程中完成一次性创建。

printf("Enter the maximum number of movie list: ");
scanf("%d", &n);
struct film * movies_list = (struct film *)malloc(n*sizeof(struct film));

以上,虽然我们已经实现了动态分配数组的大小,但是理想的情况应该是,用户可以不确定的添加数据,而不是先制定要输入多少项。如果输入3部电影,程序就调用malloc() 3次;如果输入100部电影,程序就调用malloc()100次。

这样会带来一个新的问题,如果不是一次性申请内存,那么无法保证分配到连续的内存块。

同样是完成5个film结构体的内存申请。

第一种方法,调用malloc()一次,为5个film结构体分配内存空间。

struct film * movie;
movie = (struct film *) malloc(5*sizeof(struct film);

分配的内存是连续的。 

第二种方法,调用malloc() 5次,分别为每个film结构请求分配足够的空间。

int i;
struct film *movies[s];
for (i = 0; i < 5; i++)
    movies[i] = (struct films *) malloc(sizeof(struct films));

 分配的内存地址是不连续的。

对于动态申请内存所带来的地址的不连续,我们应该如何解决呢?

答案便是使用链表结构。我们需要再原来的结构体中接入一个指针来追踪即将待生成的film数据。

struct film {
    char title[TSIZE]; 
    int rating;
    struct film * next;
};

虽然结构不能含有与本身类型相同的机构,但是可以含有指向同类型结构的指针。这种定义是定义链表(linked list)的基础,链表中每一项都包含着在何处能找到下一项的信息。

对于一个链表,我们需要一个头指针(head pointer)指向链表中的第一个成员,next指向下一个成员,最后一个成员的next指针设置为NULL,表示没有其他成员了。如下:

#define TSIZE 45 
struct film {
    char title[TSIZE]; 
    int rating;
    struct film * next;
};
struct film * head;

假设用户输入的片名是 Modern Times,等级为 10。那么,链表结构如下:

 假设用户加入新的电影 Midnight inParis 和 评分 8。那么结构更新如下:

每加入一部新的电影,就以相同的方式处理。

 

 以上,我们便了解了链接的原理,程序的实现我们便留给《C语言链表—实战篇》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值