最通俗易懂的链表讲解

我先来带你认识一下什么是链表:

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。
在这里插入图片描述
看完上面这段话,是不是觉得这十几年的教育都白学了。明明每个字都认识,但是为什么连在一起就看不懂了呢?

简单来说:
链表就是不再按照顺序来连接了,链表的开始是由头指针开始的,头指针指向第一个节点或者头结点。每个结点都有两部分组成:一个数据域用来存储你这个元素的数据,一个指针域用来存储下一个数据的位置,这个是不是感觉有点像港片里面的线人?一旦你的直属上司挂掉了,你就变成gu儿了? 同理,如果你的指针域没有指向下一个结点的话(最后一个结点的指针域都是指向“NULL”的)。那么就代表这个链表已经结束了。


了解了链表的基础,那么现在我们就来看看链表的数据结构:

//数据结构
typedef struct monster{
    
    
      int id;      //编号
      char *name;  //名称
        
      //指向下一结点的指针
      struct monster *pNext;
}Monster;

光看结构是看不出什么来的,所以还是要大家来实战一下来加强印象:

//示例
typedef struct Monster{
    
    
    int id;
    char *name;
    struct Monter *next;   //指向下个结点的指针
}Monster;

void test()
{
    
    
    Monster monster1 = {
    
    1, "乔布斯"};
   Monster monster2 = {
    
    2, "比尔·盖茨"};
   Monster monster3 = {
    
    3, "巴菲特"};
   
   //monster1 就是头指针
   monster1.next = &monster2;
   monster2.next = &monster3;
   monster3.next = NULL;
}

这里再给大家讲讲头指针和头结点的基本概念:

头指针:链表中的第一个结点的存储位置;
头结点:在单链表的第一个结点前附设的一个结点。

两者的异同点

头指针 头结点
若链表有头结点,则是指向头结点的指针;若没有则是链表指向第一个结点的指针; 头结点是为了操作的统一和方便而设立的,放在第一个结点之前;其数据域一般无意义(但是可以存储链表的长度)
头指针具有表示作用,所以常常用头指针表示链表的名字; 有了头结点,在第一个结点前插入和删除第一个几点时,操作与其他结点就统一了。
无论链表是否为空,头指针均不为空。 头指针是链表的必要元素 头结点不一定是链表的必须要素。

最后总结:

  1. 链表结点包括数据域和指针域
  2. 链表是由n 个结点链结成,第一个结点的存储位置叫做头指针,最后一个结点的指针为“空”

相较于顺序表的优点:

  • 定义时不用规定长度;
  • 存储的元素个数不受限制;
  • 插入和删除元素时,不用移动其它元素。

好了,看到这里的时候。我们就要开始我们的老规矩准备说再见了。
这次这次给大家普及了一点链表的知识,下一篇文章我会带大家学习“链表”的大儿子“单链表”
如果觉得本篇文章对你有帮助的话,麻烦各位兄弟萌点个赞帮忙转发一下~
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43776724/article/details/105234248