1. 链表概述
链表是一种物理存储单元上非连续, 非顺序的存储结构, 数据元素的逻辑顺序是通过链表中的指针链接
次序实现的, 链表由一系列节点(链表中的每个元素称为节点)组成, 节点可在运行时动态生成.
1.1. 链表与数组优缺点
优点:
1. 不需要于预先知道数据大小, 可以动态改变大小
2. 链表结构可以充分利用计算机内存空间, 灵活实现内存的动态管理.
3. 常规数组排列关联项目的方式可能不同于这些数据项目在记忆体或磁盘上的顺序, 数据的存取
往往要在不同的排列顺序中转换, 链表允许插入和移除链表上任意位置上的节点.
缺点:
1. 失去了随机读取的优点, 数组可以根据下标随机读取, 链表需要遍历, 效率低下.
2. 链表增加了节点的指针域, 空间开销较大.
1.2. 链表的分类
根据存储方式不同可分为 线性表 和 非线性表.
还可以根据遍历方式不同分为 单向链表, 双向链表, 循环链表.
2. 链表操作
链表常用操作与数据库类似, 增, 删, 改, 查.
此处以双向链表进行演示, 单向, 循环链表操作类似.
2.1. 链表定义
struct list_node
{
struct list_node *next;
struct list_node *prev;
};
typedef struct list_node list_t;
2.2. 链表初始化
void list_init(list_t *l)
{
l->next = l->prev = l;
}
2.3. 链表插入节点
双向链表的插入分为 表头前插 和 表头后插.
2.3.1. 表头前插
void list_insert_before(list_t *l, list_t *n)
{
l->prev->next = n;
n->prev = l->prev;
l->prev = n;
n->next = l;
}
2.3.2. 表头后插
void list_insert_after(list_t *l, list_t *n)
{
l->next->prev = n;
n->next = l->next;
l->next = n;
n->prev = l;
}
2.3.3. 节点删除
void list_remove(list_t *n)
{
n->next->prev = n->prev;
n->prev->next = n->next;
n->next = n->prev = n;
}