之前,我们提到了顺序存储的线性表.并且举了一个数组的例子.这次我们来说一下线性表的另外一种存储结构->链式存储(链表).
链表中的元素通过指针相连.
typedef struct Node {
XXXType data;// 数据
struct Node *next;// 下一个节点
}Node *LinkList;
我们可以通过头节点来获取整个链表.并且特殊的是最后一个节点指向一个空地址NULL.不过不是每种链表的尾节点都指向NULL.(譬如循环链表).
链表删除和添加元素
对于链表来说.插入和删除的复杂度就比较低了.毕竟只需要操作相邻的节点即可.
比如添加,我只需要将要插入的位置的前一个节点的next指向当前要插入的节点.当前要插入的节点再指向下一个节点即可.时间复杂度就为O(1).
链表的查询
然而链表的查询就没有顺序表方便了.顺序表由于在内存中是顺序存储的.可以通过下标直接访问.但是对于链表,是由指针链接起来的.每次访问都需要从头节点开始通过next指针来访问.所以链表的随机访问的时间复杂度为O(n).
循环链表和双向链表
这是两种特殊的链表.拿普通的单链表作比喻.
**循环链表:**就是末尾的next指向了链表中前面的某个元素.构成了一个环.如果需要检测一个链表是不是循环链表,我们只需要使用两个指针即可.一个指针一次挪动一位.一个指针一次挪动两位.当两个指针的位置相同时.就说明这个链表是循环链表
**双向链表:**普通的单向链表知道一个节点的地址,访问next的时间复杂度为O(1),但是想要访问前一个节点就必须要从头节点开始通过next访问,时间复杂度就是O(n),为了解决这个问题,就出现了一个叫双向链表的东西,他比普通的单向链表多了一个previous指针来指向前面一个节点.虽说双向链表支持双向便利.但是多了一个前驱指针的存储空间,所以同数据下双向链表的存储空间占用会大一些