一:概述
链表(Linked list)由一些节点组成,物理存储非连续的线性表。其中每个节点都会存储下个节点的指针,由于实际存储空间不连续,对链表插入节点,删除节点可以达到O(1)的复杂度,但是对一个节点的访问需要O(n)的时间。
链表有单向链表,双向链表。
二:单向链表
单向链表的每个节点有数据项和指针(指向下个节点地址数据)组成,下图为一个单向链表,表头没有数据项,只有指向下一个节点的指针。表尾节点指向下一个节点pNext指针为NULL(空)。
结构体表示为:
//单向链表节点数据结构
typedef struct linkNode
{
void *val; //数据项(任意类型)
struct linkNode *next;
}node;
插入节点操作:
单向链表中由四个数据节点,数据1,数据2,数据3,数据4,现在数据1和数据2节点间插入数据5,只需把数据1节点的pNext指向新的节点,把新节点的pNext指向数据2节点即可。
删除节点操作:
删除节点2,只需把第一个节点的pNext执行数据3节点,同时释放节点2的存储空间即可。
三:双向链表
双向链表有别于单向的,每个节点除了数据项外有两个指针分别指向前一个节点和后一个节点,占用空间会大一些,可以实现从头到尾的遍历,又可以从尾到头遍历。
结构体表示为:
//双向链表节点数据结构
typedef struct dLinkNode
{
void *val; //数据项(任意类型)
struct dLinkNode *prev;
struct dLinkNode *next;
}node;
插入节点操作:
节点1与节点2之间插入新节点5,需要把节点1的pNext指向节点5,节点5的pHead指向节点1,节点5的pNext指向节点2,节点2的pHead指向节点5,如下图所示:
删除节点操作:
删除节点2,把节点1的pNext指向节点3,把节点3的pHead指向节点1,同时释放节点2的存储空间即可。
四:链表与数组区别
1.链表存储空间不连续,可以充分利用碎片空间,数组的存储空间是连续的,内存空间要求高,必须要有足够连续的内存空间。
2.链表的插入删除元素简单,无需对元素移动,但查询元素会慢,数组对元素的插入删除较复杂,同时使用时要预先指定长度,但数组的查询会很快。