转载:https://blog.csdn.net/morixinguan/article/details/68951912
为什么要学习链表?
链表主要有以下几大特性:
1、解决数组无法存储多种数据类型的问题。
2、解决数组中,元素个数无法改变的限制(C99的变长数组,C++也有变长数组可以实现)。
3、数组移动元素的过程中,要对元素进行大范围的移动,很耗时间,效率也不高。
先来感性的认识一下链表,我们先来认识下简单的链表:
从这幅图我们得出以下信息:
这个简单链表的构成:
头指针(Header),若干个节点(节点包括了数据域和指针域),最后一个节点要指向空。
实现原理:头指针指向链表的第一个节点,然后第一个节点中的指针指向下一个节点,然后依次指到最后一个节点,这样就构成了一条链表。
接下来看看链表的数据结构:
struct list_node
{
int data ; //数据域,用于存储数据
struct list_node *next ; //指针,可以用来访问节点数据,也可以遍历,指向下一个节点
};
那么如何来创建一个链表的一个节点呢?
我们写个程序演示一下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct list_node
{
int data ;
struct list_node *next ;
};
typedef struct list_node list_single ;
int main(void)
{
list_single *node = NULL ; //1、首先,当然是定义一个头指针
node = (list_single *)malloc(sizeof(list_single)); //2、然后分配内存空间
if(node == NULL){
printf("malloc fair!\n");
}
memset(node,0,sizeof(list_single)); //3、清一下
node->data = 100 ; //4、给链表节点的数据赋值
node->next = NULL ; //5、将链表的指针域指向空
printf("%d\n",node->data);
free(node);
return 0 ;
}
那么,这仅仅只是创建一个链表中的一个节点,为了好看,我们把创建节点封装成函数,以后想创建多少个节点,我们就可以反复调用一个函数来创建,会很方便:
list_single *create_list_node(int data)
{
list_single *node = NULL ;
node = (list_single *)malloc(sizeof(list_single));
if(node == NULL){
printf("malloc fair!\n");
}
memset(node,0,sizeof(list_single));
node->data = data ;
node->next = NULL ;
return node ;
}
接下来在程序上完成的程序:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct list_node
{
int data ;
struct list_node *next ;
};
typedef struct list_node list_single ;
list_single *create_list_node(int data)
{
list_single *node = NULL ;
node = (list_single *)malloc(sizeof(list_single));
if(node == NULL){
printf("malloc fair!\n");
}
memset(node,0,sizeof(list_single));
node->data = data ;
node->next = NULL ;
return node ;
}
int main(void)
{
int data = 100 ;
list_single *node_ptr = create_list_node(data); //创建一个节点
printf("node_ptr->data=%d\n",node_ptr->data); //打印节点里的数据
printf("node_ptr->next=%d\n",node_ptr->next);
free(node_ptr);
return 0 ;
}
执行结果 :
这样我们就完成一个链表节点的创建了,那么它现在的样子如下图:
链表的结构里,数据存储了100,因为这个链表只有一个节点,所以它的指针域指向了NULL。
我自己学习链表的时候,晕头转向了一两个星期,很多人对于数组,对于地址还有指针的作用了解的不够清晰明确的话,很容易就会迷惑:明明数组这么方便理解而且操作简单,为什么还要这么麻烦用易混淆的指针去处理数据?所以我在这做一个简单的解释。
现在让我们假设,你是一个有着强迫症的手办爱好者。现在你新入手了一个擎天柱的模型(代指你要录入的数据库),为了好好保存手办,又得避免老妈骂你的宝贝占地方,你现在有两个选择:
第一:为了节省空间,做一个尽可能小的玻璃罩,把擎天柱完整的放进去展览。(建一个内存合理的数组)
第二:架子上放不下这么大一个模型,但你的各个抽屉有很多小空间。而你的手办是可拆卸的,所以你可以把擎天柱拆成:头部,躯干,双臂,双腿,然后放在四个不同的抽屉里。(建一个链表)
如果是第一种方法,虽然看起来很直观,但是也有问题:这个擎天柱的手办出品方还会在未来的日子里继续出售其他附加零件(插入新的数据),如果零件多了,你的玻璃罩就小了,你必须得重新定制一个更大的,还得为了凸起的零件绞尽脑汁把罩子设计成奇形怪状的样子(数组在后续的插入删除数据方面很麻烦,不适合增改数据。)
但如果是第二种方法,你只需要再找一个柜子的旮旯,把零件塞进去就行。
不过第二种方法也不是没有弊端:零件一多,你就记不住都放在哪了。而你又有强迫症,必须得按从头到脚的顺序去寻找,安装零件,这样要怎么办呢?
有了!
我们在写字桌上贴一个字条:擎天柱的脑袋在左手边第二个抽屉里。
然后在脑袋在的抽屉里再放一张字条:躯干在电视下面的右起第三个柜子里……
最后在双腿的最后一个柜子里写:这是最后一个零件,全部找齐了。(链表的指针就是这些小纸条,用来寻找下一个数据结构体所在的地址,而零件就是结构体里 的数据。)。
如果你后续购入了需要按在手臂上的等离子炮手办零件,你只需要在放手臂的抽屉里重新放一张纸条:等离子炮在老爸的衣柜第二层;然后在衣柜里的等离子炮旁边放一张纸条:双腿的零件在厨房……你不用每次重新把等离子炮后面的零件都挪个地方,只需要更改一下纸条就行。而最关键的就是桌子上最显眼的第一张纸条(也就是头指针head),如果没有这张纸条,你就根本无法顺藤摸瓜找到零件了。
这两种方法的特点在于:第一种方法能够一目了然找到所有零件:反正零件都在一起,按顺序往下翻就行;但链表的方式是:你要想找到等离子炮,就得先找到头,再找到躯干,再找到手臂,最后才能根据手臂旁的纸条找到等离子炮。
好啦,是不是对于链表的理解更明确了一些呢?
---------------------
作者:Mr_J0304
来源:CSDN
原文:https://blog.csdn.net/Mr_J0304/article/details/79678873
版权声明:本文为博主原创文章,转载请附上博文链接!