线性表之静态链表

1. 静态链表的设计

1.1 定义静态链表

        链表是由多个相同类型的节点组成的线性表,它的每个节点都包含一个数据项和一个指向下一个节点的指针,链表中各个节点的地址是不连续的。

下面是一个用于存储整形数据的链表节点结构:

struct Node
{
    int data;
    struct Node* next;
};
  • data:用于存储实际数据
  • next:用于连接当前节点的后继节点,存储的是下一个节点的地址(很多资料中将其称之为游标)

        静态链表是一种使用数组实现的链表,通常用于环境中无法使用指针的情况。这种结构在内存中是连续存储的,但节点的位置可以变化,因此称为静态链表。

        静态链表的节点结构和链表类似,但是不完全相同,当前节点连接后继节点使用的是索引而不是指针。

下面是一个用于存储整形数据的链表节点结构:

struct Node
{
    int data;
    int next; 
};
  • data:用于存储实际数据
  • next:使用索引的方式记录后继节点的位置

        由于静态链表是一个数组,也就是说在存储数据之前元素对应的存储空间就已经存在了,此时我们就需要考虑以下几个问题:

  • 如何判断当前节点是一个空闲节点?
  • 如何判断当前节点是一个有效的数据节点?
  • 如何判断当前节点是链表的尾节点?

        由于链表的数据域data的值是千变万化的,所以我们只能在它的next域上下功夫,在使用静态链表之前可以对它的值做如下规定(不考虑头结点):

  • next == -1:当前节点为静态链表的尾节点
  • next == -2:当前节点为静态链表的空闲节点
  • next >= 0:当前节点为静态链表的有效的数据节点

1.2 链表头结点

        不论是链表(动态)还是静态链表根据处理方式的不同,都可以分为两大类:带头结点的链表和不带头结点的链表。

        带头结点:链表的第一个节点(头结点)的data域不存储数据,next域记录的是第一个数据节点的位置(索引或者地址)
        不带头结点:链表的第一个节点的data域存储数据,next域记录的是第二个数据节点的位置(索引或者地址)
        一般情况下建议大家使用带头结点的链表,带头结点的链表避免了链表中没有节点的这种情况(空链表指的是链表中没有数据节点),减少了bug的产生,并且更容易处理和维护。

下图描述的是一个静态链表,请大家动脑分析,完成对这个链表的遍历。

        虽然数组中存储的数据的按照下边遍历顺序为:null、a、b、c、f、d、g,但实际上在静态链表中存储的数据顺序并非如此。其中的关键点就是:先看各个节点中的 next 域记录的位置,然后再把这个位置作为数组的下标,去访问对应的数组元素。

  • 数组0号元素为静态链表的头结点,next=6,所以第1个数据为g
  • 数组6号元素为静态链表的数据节点,next=1,所以第2个数据节点为a
  • 数组1号元素为静态链表的数据节点,next=5,所以第3个数据节点为d
  • 数组5号元素为静态链表的数据节点,next=4,所以第4个数据节点为f
  • 数组4号元素为静态链表的数据节点,next=2,所以第5个数据节点为b
  • 数组2号元素为静态链表的数据节点,next=3,所以第6个数据节点为c
  • 数组3号元素为静态链表的尾节点,没有后继节点

因此遍历静态链表,得到的序列应该是:g、a、d、f、b、c

2. 静态链表和数组

        静态链表和数组的本质是相同的,但是在使用方式上又有所不同,下面就给大家总结一下二者的优缺点:

插入删除操作,静态链表效率高

  • 静态链表只需要修改对应节点的next域的值,需不要移动元素
  • 数组在插入新节点需要大量元素后移,删除节点需要大量元素前移

访问指定位置的元素,数组效率高

  • 静态链表需要遍历才能找到这个节点
  • 数组通过下标就可以找到该节点了

默认情况下内存大小是固定的

  • 申请的内存空间大,但是数据量少,浪费存储空间
  • 申请的内存空间小,但是数据量大,内存不够用

        静态链表和数组是对同一块连续内存的两种不同使用方式,二者没有孰优孰劣之分,作为一名合格的程序猿要做的就是具体问题具体分析,从众多解决方案中找出一个最优解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值