一、链表概述
链表是一种线性数据结构,通过节点之间的指针链接实现数据存储,属于链式存储结构。与顺序表(数组)相比,链表在动态内存分配和插入删除操作上具有明显优势,但随机访问效率较低。
二、单向链表
1. 结构特点
-
每个节点包含数据域和指向下一个节点的指针。
-
只能从头节点开始顺序访问,不支持反向遍历。
2. 基本操作
-
创建与销毁:动态分配节点内存,遍历释放。
cpp
note_t *creat(void)
{
note_t *pnew = NULL;
pnew = malloc(sizeof(note_t));
if(NULL == pnew)
{
perror("malloc fail");
return NULL;
}
pnew -> pnext = NULL;
return pnew;
}
int insert(note_t *phead,DateType TmpData)
{
note_t *pnew = NULL;
pnew = malloc(sizeof(note_t));
if(NULL == pnew)
{
perror("fail to malloc");
return -1;
}
pnew->Date = TmpData;
pnew->pnext = phead->pnext;
phead->pnext = pnew;
return 0;
}
-
插入:可在头、尾或任意位置插入,时间复杂度为 O(1)O(1)(头插)或 O(n)O(n)(中间插入)。
-
删除:需定位前驱节点,修改指针指向,释放节点内存。
cpp
int delete(note_t *phead,DateType TmpData)
{
note_t *ptmp = NULL;
note_t *pter = NULL;
int cnt = 0;
pter = phead;
ptmp = phead->pnext;
while(ptmp != NULL)
{
if(ptmp->Date == TmpData)
{
pter->pnext = ptmp->pnext;
free(ptmp);
cnt++;
ptmp = pter->pnext;
}
else
{
ptmp = ptmp->pnext;
pter = pter->pnext;
}
}
return cnt;
}
- 遍历 :从头节点开始,依次访问直到指针为
NULL。
3. 进阶问题:环检测与处理
-
判断是否有环:使用快慢指针(Floyd 判圈算法),若相遇则有环。
-
求环长:从相遇点出发,指针再次回到该点所走过的节点数即为环长。
-
找环入口:两指针分别从头节点和相遇点同步前进,再次相遇点即为环入口。
cpp
int IsCircleList(Node_t *pHead, int *plen, Node_t **ppTmpNode)
{
Node_t *pFast = NULL;
Node_t *pSlow = NULL;
Node_t *pMeetNode = NULL;
int len = 0;
pSlow = pFast = pHead->pNext;
while (1)
{
pFast = pFast->pNext;
if (NULL == pFast)
{
return 0;
}
pFast = pFast->pNext;
if (NULL == pFast)
{
return 0;
}
pSlow = pSlow->pNext;
if (pSlow == pFast)
{
pMeetNode = pSlow;
break;
}
}
pSlow = pMeetNode->pNext;
len++;
while (pSlow != pMeetNode)
{
len++;
pSlow = pSlow->pNext;
}
*plen = len;
pFast = pMeetNode;
pSlow = pHead->pNext;
while (pFast != pSlow)
{
pFast = pFast->pNext;
pSlow = pSlow->pNext;
}
*ppTmpNode = pSlow;
return 1;
}
三、双向链表
1. 结构特点
-
节点除数据域外,包含前驱指针
prev和后继指针next。 -
支持双向遍历,可从任意节点向前或向后访问。
2. 操作优势
-
插入与删除:在已知节点位置时,时间复杂度为 O(1)O(1),因可直接修改前驱和后继指针。
-
遍历:支持正向与反向遍历,灵活性更高。
3. 实现要点
-
创建与销毁:需同时维护双向指针关系。
-
头插与尾插 :注意更新头节点或尾节点的
prev与next。 -
删除操作:需处理被删除节点前后节点的指针指向,避免断链。
四、链式存储与顺序存储对比
| 特性 | 顺序存储(数组) | 链式存储(链表) |
|---|---|---|
| 访问效率 | O(1)O(1) | O(n)O(n) |
| 插入删除效率 | O(n)O(n) | O(1)O(1)(已知位置) |
| 空间利用 | 连续空间,可能浪费 | 动态分配,利用率高 |
| 内存开销 | 仅数据 | 数据 + 指针 |
今日练习
1.双向链表的创建,插入,删除,寻找,替换,销毁。




