静态链表详解

前言

这篇文章开始,我们来讲述一下静态链表。

什么是静态链表

静态链表是分配一整片连续的内存空间,各个结点集中安置,而不是像单链表那样,每个结点在内存中分散存储。

image-20220710182045769

如上如的存储方式,优点类似于顺序表,但是在这一整片连续的内存空间中,元素不是按照顺序存储的。而是可以打乱顺序存储,这时候就需要将结点分为两个部分,一个部分存储数据元素,另一个部分存储下一个结点所在的下标(称其为游标),比如:头结点存放的下标(游标)为2,代表在2的位置上是静态链表的第一个真正存放数据的结点。头结点的地址为addr,那么静态链表的第一个真正存放数据的结点地址就为:addr + 8*2(这里假设数据元素和游标的大小都为4B)。

在单链表中如果想要表示表尾结点,会让该结点的尾指针指向NULL。而在静态链表中会将游标设置为-1。

用代码定义一个静态链表

#define MaxSize 10			// 静态链表的最大长度
struct Node{				// 静态链表结构类型的定义
    ElemType data;			// 数据域
    int next;				// 游标
}

我们需要的是一整块连续的空间,所以我们可以用数据的方式声明

void testSLinkList(){
    strcut Node a[MaxSize];		// 数组a作为静态链表
}

image-20220710182837633

书上给出的代码比较少见

#define MaxSize 10
typedef struct{
    ElemType data;
    int next;
}SLinkList[MaxSize];

// 等价于

#define MaxSize 10
struct Node{
    ElemType data;
    int next;
};
typedef struct Node SLinkList[MaxSize];

如果用以上的方式定义结构类型,那么我们的声明就会变成

void testSLinkList(){
    SLinkList a;
}

上述这种方式其实意思就是声明一个静态链表a,并且其最大长度为MaxSize,等价于下面这种写法

void testSLinkList(){
    struct Node a[MaxSize];
}

这种写法其实就类似于前面的LNode *LinkList的区别一样,功能完全相同,只是增加了代码的可读性。

静态链表基本操作的实现

初始化单链表

需要将a[0](头结点)的next(游标)设置为-1,并且将空的未存入数据的位置上将游标设置为-2或者其他值(这在后续的插入中有用)

静态链表的查找

从头结点出发挨个往后遍历结点。所以时间复杂度为O(n)

静态链表的插入

静态链表的插入操作步骤:

  1. 找到一个空的结点,存入数据
    • 这里就涉及到要如何找到空的结点
    • 我们在初始化的时候就已经说过将空闲的结点游标设置为-2或者其他特殊的值,那么我们只需要遍历时通过游标是否为-2或者特殊的值来判断该结点是否为空
  2. 从头结点出发找到位序为i-1的结点
  3. 修改新结点的next为-1
  4. 修改i-1的结点的next(游标)

静态链表的删除

静态链表的删除步骤:

  1. 从头结点出发找到前驱结点
  2. 修改前驱节点的游标
  3. 被删除结点next设置为-2

总结

静态链表在408的考察中并不是很多,并且也很少回去考代码实现,所以这里知识简单的介绍。

静态链表其实就是用数组的方式实现的链表。

现在已经用的很少了,只有早期的不支持指针的低级语言会使用该方法来达到类似单链表一样的效果。

优点

  1. 增、删操作不需要大量移动元素

缺点

  1. 不能随机存取,只能从头结点开始以此往后查找
  2. 容量固定不可变

适用场景

  1. 不支持指针的低级语言
  2. 数据元素数量固定不变的场景(如操作系统的文件分配表FAT)

(等学到《操作系统》中的文件管理的时候可以再回过头来体会静态列表有什么作用)

结束语

已同步更新至个人博客:https://www.hibugs.net/index.php/stlinklist/

本人菜鸟一枚,仅分享学习笔记和经验。若有错误欢迎指出!共同学习、共同进步 😃

如果您觉得我的文章对您有所帮助,希望可以点个赞和关注,支持一下!十分感谢~(若您不想也没关系,只要文章能够对您有所帮助就是我最大的动力!)

下一篇文章传送门:正在更新,敬请期待…

  • 29
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
静态链表是一种使用数组实现的链表结构,它通过数组中的元素来模拟链表中的节点,并使用一个特殊的指针(游标)来表示节点之间的逻辑关系。静态链表的优点是实现简单,不需要频繁地申请和释放内存空间,但缺点是插入和删除操作比较麻烦,需要手动维护游标指针。 以下是一个简单的Python静态链表的实现示例[^1]: ```python class StaticLinkedList: def __init__(self, size): self.data = [None] * size # 存储数据的数组 self.next = [i + 1 for i in range(size)] # 游标数组,用于维护节点之间的逻辑关系 self.next[-1] = -1 # 最后一个元素的游标为-1,表示链表的末尾 self.head = -1 # 头指针,指向链表的第一个节点 def is_empty(self): return self.head == -1 def is_full(self): return self.next == -1 def insert(self, value): if self.is_full(): print("StaticLinkedList is full") return new_node = self.next # 获取一个空闲节点 self.next = self.next[new_node] # 更新空闲节点的游标 self.data[new_node] = value # 在空闲节点中存储数据 if self.is_empty(): self.head = new_node self.next[new_node] = -1 else: current = self.head while self.next[current] != -1: current = self.next[current] self.next[current] = new_node self.next[new_node] = -1 def delete(self, value): if self.is_empty(): print("StaticLinkedList is empty") return prev = -1 current = self.head while current != -1: if self.data[current] == value: break prev = current current = self.next[current] if current == -1: print("Value not found") return if prev == -1: self.head = self.next[current] else: self.next[prev] = self.next[current] self.next[current] = self.next # 将删除的节点加入空闲节点链表 self.next = current def display(self): if self.is_empty(): print("StaticLinkedList is empty") return current = self.head while current != -1: print(self.data[current], end=" ") current = self.next[current] print() # 创建一个容量为5的静态链表 static_list = StaticLinkedList(5) # 插入数据 static_list.insert(1) static_list.insert(2) static_list.insert(3) # 删除数据 static_list.delete(2) # 显示链表中的数据 static_list.display() ``` 输出结果为: ``` 1 3 ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值