# 单链表经典题目总结（C语言）

15 篇文章 0 订阅

## 单链表面试题 + 画图分析 + 源代码

### 1.移除链表元素

#### 源代码

struct ListNode* removeElements(struct ListNode* head, int val)
{

struct ListNode* prev = NULL;
while (cur)
{
if (cur->val != val)
{
prev = cur;
cur = cur->next;

}
else
{
//解决prev为空的情况
if (prev == NULL)
{
free(cur);
}
else
{
//常规移除链表元素操作
prev->next = cur->next;
free(cur);
cur = NULL;
cur = prev->next;
}
}
}
}


struct ListNode* removeElements(struct ListNode* head, int val)
{
//建立新链表的头节点和尾节点
struct ListNode* tail = NULL;

while (cur)
{
if(cur->val != val)
{
//解决新节点为空的情况
if(NULL == tail)
{
}
else
{
tail->next = cur;
tail = tail->next;
}
cur = cur->next;
}
else
{
//释放需要移除的节点，防止内存泄漏
struct ListNode* next = cur->next;
free(cur);
cur = next;
}
}
//把最后一个节点的next置空
if(tail)
{
tail->next = NULL;
}

}


### 2.反转链表

#### 源代码

struct ListNode* reverseList(struct ListNode* head)
{
{
return NULL;
}
struct ListNode* n1 = NULL;

while (n2)
{
//reverse
n2->next = n1;

//迭代
n1 = n2;
n2 = n3;
if (n3)
{
n3 = n3->next;
}
}
return n1;
}


struct ListNode* reverseList(struct ListNode* head)
{
//建立新的头节点

//建立新的节点，进行循环
while (cur)
{
//保存当前节点的下一个节点，用来更新
struct ListNode* next = cur->next;

cur = next;
}
//返回新的头节点
}


### 3.链表的中间结点

#### 源代码

struct ListNode* middleNode(struct ListNode* head)
{
//慢指针
//快指针

//由上图分析，两种遍历结束情况，并在一起。
while (fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
}
//返回慢指针，慢指针就是指向链表的中间节点
return slow;
}


### 4.链表中倒数第k个结点

#### 源代码

struct ListNode* FindKthToTail(struct ListNode* pListHead, int k )
{
// 建立快慢指针

//快指针先走k步
while (k--)
{
//判断一下，如果快指针还没走k步就为空，就代表链表找不到第k个节点，属于野指针
if(fast == NULL)
{
return NULL;
}
fast = fast->next;
}

//快慢指针一起走
while (fast)
{
fast = fast->next;
slow = slow->next;
}
return slow;
}


### 5. 合并两个有序链表

#### 源代码

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
//定义合并后链表的哨兵位
struct ListNode* guard = (struct ListNode*)malloc(sizeof(struct ListNode));
struct ListNode* tail = guard;
//这里要对头节点置空
guard->next = NULL;

//定义两个链表的头节点，进行遍历
struct ListNode* cur1 = list1;
struct ListNode* cur2 = list2;
while (cur1 && cur2)
{
//符合条件就移动到新的链表tail后
if (cur1->val < cur2->val)
{
tail->next = cur1;
tail = tail->next;
cur1 =cur1->next;
}
else
{
tail->next = cur2;
tail = tail->next;
cur2 =cur2->next;
}
}
//当cur1或者cur2某一链表为空的时候，把不为空的直接链接到tail后
if (cur1)
{
tail->next = cur1;
}
if(cur2)
{
tail->next = cur2;
}

//释放哨兵位节点
struct ListNode* next = guard->next;
free(guard);
guard =NULL;

//返回新链表的头节点
return next;
}


### 6. 链表分割

#### 源代码

struct ListNode* partition(struct ListNode* pHead, int x)
{
//建立存放大值链表的哨兵位节点
struct ListNode* gGarud;
//建立存放大值链表的哨兵位节点
struct ListNode* lGarud;

//与上面的哨兵位对应的链表尾节点
struct ListNode* gTail;
struct ListNode* lTail;

gGarud = gTail = (struct ListNode*)malloc(sizeof(struct ListNode));
lGarud = lTail = (struct ListNode*)malloc(sizeof(struct ListNode));

//对头节点置空
gTail->next = NULL;
lTail->next = NULL;

while (cur)
{
if (cur->val >= x)
{
gTail->next = cur;
gTail = gTail->next;
}
else
{
lTail->next = cur;
lTail = lTail->next;
}
cur = cur->next;
}
//把存放小值的链表链接到存放大值链表的前面
lTail->next = gGarud->next;

//对大值链表的尾节点的next置空
gTail->next = NULL;

//释放
free(gGarud);
free(lGarud);

//返回分割后链表的头节点
}


### 7. 链表的回文结构

#### 源代码

//寻找中间节点
{
//慢指针
//快指针

//由上图分析，两种遍历结束情况，并在一起。
while (fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
}
//返回慢指针，慢指针就是指向链表的中间节点
return slow;
}

//链表倒置
{
//建立新的头节点

//建立新的节点，进行循环
while (cur)
{
//保存当前节点的下一个节点，用来更新
struct ListNode* next = cur->next;

cur = next;
}
//返回新的头节点
}

//判断是不是回文结构
{

{
{
return false;
}

//更新递进
}
return true;
}


### 8. 相交链表

#### 源代码

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB)
{
//分别重新定义两个头节点，因为后面还需要使用头节点，所以不能直接使用所给的头节点，以防找不到链表的头节点
int lenA = 0;
int lenB = 0;
//分别进行循环，计算两个链表的长度
while (curA)
{
curA = curA->next;
lenA++;
}
while (curB)
{
curB = curB->next;
lenB++;
}

//判断，如果两个链表的尾指针不相等，也就意味着没有相交的地方，所以没必要向下执行，直接返回NULL
if (curA != curB)
{
return NULL;
}

//abs是表示绝对值的函数，在平常使用abs时，需要使用库函数<stdlib.h>
int absVal = abs(lenA - lenB);

//如果假设不成立，在这里面改一下
if (lenA > lenB)
{
}

//让长链表先走absVal步
while (absVal--)
{
longList = longList->next;
}

//寻找两个链表相等的时候，那个指针就是所找的相交节点
while(longList != shortList)
{
longList = longList->next;
shortList = shortList->next;
}
//这里返回长短链表都行
return shortList;

}


## 总结

• 6
点赞
• 41
收藏
觉得还不错? 一键收藏
• 打赏
• 0
评论
08-07
04-23 1万+
07-18 904
10-13 1594
10-13 1172
03-22
08-07 1314
03-18 1577
01-01 4630
03-19 239

kpl_20

¥1 ¥2 ¥4 ¥6 ¥10 ¥20

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