Skip to content

Commit 0ab7af0

Browse files
committed
Publish linked list algorithm article
1 parent 61431be commit 0ab7af0

6 files changed

Lines changed: 426 additions & 1 deletion

File tree

public/blogs/categories.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"categories": [
33
"ComputerNetworks",
4+
"algorithm",
45
"docker"
56
]
67
}

public/blogs/index.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
11
[
2+
{
3+
"slug": "linked-list-代码模板与例题",
4+
"title": "Linked List 代码模板与例题",
5+
"date": "2026-07-05",
6+
"summary": "",
7+
"tags": [
8+
"algorithm"
9+
],
10+
"category": "algorithm"
11+
},
212
{
313
"slug": "network-layer-routing-学习笔记",
414
"title": "Network Layer Routing 学习笔记",
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"title": "Linked List 代码模板与例题",
3+
"date": "2026-07-05",
4+
"summary": "",
5+
"tags": [
6+
"algorithm"
7+
],
8+
"category": "algorithm"
9+
}
Lines changed: 348 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,348 @@
1+
Linked List 代码模板与例题
2+
1.单向链表代码模板(C++)
3+
```cpp
4+
#include <iostream>
5+
using namespace std;
6+
7+
/*
8+
Node 表示“一个节点”
9+
每个节点包含两部分:
10+
1. data:存储的数据
11+
2. next:指向下一个节点的指针
12+
*/
13+
class Node {
14+
public:
15+
double data; // 当前节点存储的数据
16+
Node* next; // 指向下一个 Node 的指针
17+
};
18+
19+
20+
/*
21+
List 表示“整条链表”
22+
它不直接存所有数据,而是只保存一个 head 指针。
23+
head 指向链表的第一个节点。
24+
*/
25+
class List {
26+
public:
27+
/*
28+
Constructor 构造函数
29+
30+
创建一条空链表时,head 先指向 NULL。
31+
NULL 表示现在链表里没有任何节点。
32+
*/
33+
List() {
34+
head = NULL;
35+
}
36+
37+
/*
38+
Destructor 析构函数
39+
40+
程序结束时,释放链表中所有通过 new 创建的节点。
41+
否则会产生 memory leak。
42+
*/
43+
~List() {
44+
Node* currNode = head; // 从第一个节点开始
45+
Node* nextNode = NULL; // 用来暂存下一个节点
46+
47+
while (currNode != NULL) {
48+
nextNode = currNode->next; // 先保存下一个节点的位置
49+
delete currNode; // 删除当前节点
50+
currNode = nextNode; // 移动到下一个节点
51+
}
52+
}
53+
54+
/*
55+
判断链表是否为空
56+
57+
如果 head == NULL,说明链表没有第一个节点。
58+
*/
59+
bool IsEmpty() {
60+
return head == NULL;
61+
}
62+
63+
/*
64+
InsertNode(index, x)
65+
66+
功能:
67+
在指定位置插入一个新节点,新节点的数据是 x。
68+
69+
index 的含义:
70+
index = 0:插入到最前面,成为新的第一个节点
71+
index = 1:插入到第一个节点后面
72+
index = 2:插入到第二个节点后面
73+
74+
如果插入成功,返回新节点地址。
75+
如果插入失败,返回 NULL。
76+
*/
77+
Node* InsertNode(int index, double x) {
78+
// index 不能是负数
79+
if (index < 0) {
80+
return NULL;
81+
}
82+
83+
/*
84+
currNode 用来找到“插入位置的前一个节点”。
85+
86+
注意:
87+
当 index = 0 时,不需要找前一个节点,
88+
因为新节点要直接插到 head 前面。
89+
*/
90+
int currIndex = 1;
91+
Node* currNode = head;
92+
93+
/*
94+
目标:
95+
如果 index = 2,就要找到第 2 个节点;
96+
如果 index = 3,就要找到第 3 个节点。
97+
98+
currNode 不断向后移动:
99+
currNode = currNode->next;
100+
*/
101+
while (currNode != NULL && index > currIndex) {
102+
currNode = currNode->next;
103+
//重要:currNode->next等价于:(*currNode).next
104+
currIndex++;
105+
}
106+
107+
/*
108+
如果 index > 0,但是 currNode == NULL,
109+
说明想插入的位置超过了链表长度,插入失败。
110+
*/
111+
if (index > 0 && currNode == NULL) {
112+
return NULL;
113+
}
114+
115+
// 创建新节点
116+
Node* newNode = new Node;
117+
newNode->data = x;
118+
119+
/*
120+
情况 1:插入到链表最前面
121+
122+
原来:
123+
head -> A -> B -> NULL
124+
125+
插入 newNode 后:
126+
head -> newNode -> A -> B -> NULL
127+
*/
128+
if (index == 0) {
129+
newNode->next = head; // 新节点先指向原来的第一个节点
130+
head = newNode; // head 再改成指向新节点
131+
}
132+
133+
/*
134+
情况 2:插入到中间或末尾
135+
136+
原来:
137+
currNode -> oldNext
138+
139+
插入后:
140+
currNode -> newNode -> oldNext
141+
*/
142+
else {
143+
newNode->next = currNode->next; // 新节点先接住后面的节点
144+
currNode->next = newNode; // 前一个节点再指向新节点
145+
}
146+
147+
return newNode;
148+
}
149+
150+
/*
151+
FindNode(x)
152+
153+
功能:
154+
查找数据等于 x 的节点。
155+
156+
如果找到,返回它的位置。
157+
如果找不到,返回 0。
158+
159+
注意:
160+
这里的位置从 1 开始,不是从 0 开始。
161+
*/
162+
int FindNode(double x) {
163+
Node* currNode = head; // 从第一个节点开始找
164+
int currIndex = 1; // 位置从 1 开始
165+
166+
/*
167+
只要 currNode 不是 NULL,
168+
并且当前节点的数据不是 x,
169+
就继续往后找。
170+
*/
171+
while (currNode != NULL && currNode->data != x) {
172+
currNode = currNode->next;
173+
currIndex++;
174+
}
175+
176+
// 如果 currNode 不是 NULL,说明找到了
177+
if (currNode != NULL) {
178+
return currIndex;
179+
}
180+
181+
// 否则说明没找到
182+
return 0;
183+
}
184+
185+
/*
186+
DeleteNode(x)
187+
188+
功能:
189+
删除第一个数据等于 x 的节点。
190+
191+
如果删除成功,返回被删除节点的位置。
192+
如果没找到,返回 0。
193+
*/
194+
int DeleteNode(double x) {
195+
Node* prevNode = NULL; // 当前节点的前一个节点
196+
Node* currNode = head; // 当前正在检查的节点
197+
int currIndex = 1; // 当前节点的位置
198+
199+
/*
200+
找到 data == x 的节点。
201+
找的过程中,同时维护 prevNode 和 currNode。
202+
203+
prevNode 永远指向 currNode 的前一个节点。
204+
*/
205+
while (currNode != NULL && currNode->data != x) {
206+
prevNode = currNode;
207+
currNode = currNode->next;
208+
currIndex++;
209+
}
210+
211+
/*
212+
如果 currNode == NULL,
213+
说明整条链表找完了也没有 x。
214+
*/
215+
if (currNode == NULL) {
216+
return 0;
217+
}
218+
219+
/*
220+
情况 1:删除的不是第一个节点
221+
222+
原来:
223+
prevNode -> currNode -> nextNode
224+
225+
删除后:
226+
prevNode -> nextNode
227+
*/
228+
if (prevNode != NULL) {
229+
prevNode->next = currNode->next;
230+
delete currNode;
231+
}
232+
233+
/*
234+
情况 2:删除的是第一个节点
235+
236+
原来:
237+
head -> currNode -> nextNode
238+
239+
删除后:
240+
head -> nextNode
241+
*/
242+
else {
243+
head = currNode->next;
244+
delete currNode;
245+
}
246+
247+
return currIndex;
248+
}
249+
250+
/*
251+
DisplayList()
252+
253+
功能:
254+
打印链表中所有节点的数据,
255+
并统计节点数量。
256+
*/
257+
void DisplayList() {
258+
int num = 0;
259+
Node* currNode = head;
260+
261+
while (currNode != NULL) {
262+
cout << currNode->data << endl;
263+
currNode = currNode->next;
264+
num++;
265+
}
266+
267+
cout << "Number of nodes in the list: " << num << endl;
268+
}
269+
270+
private:
271+
/*
272+
head 是整条链表的入口。
273+
274+
如果:
275+
head == NULL
276+
277+
说明链表为空。
278+
279+
如果:
280+
head -> 6 -> 7 -> 5 -> NULL
281+
282+
说明 head 指向第一个节点 6,
283+
然后 6 的 next 指向 7,
284+
7 的 next 指向 5,
285+
5 的 next 指向 NULL。
286+
*/
287+
Node* head;
288+
};
289+
290+
291+
int main() {
292+
List list;
293+
294+
/*
295+
插入节点
296+
注意 index 的含义:
297+
298+
InsertNode(0, 7.0)
299+
表示把 7.0 插入到最前面。
300+
301+
InsertNode(1, 5.0)
302+
表示把 5.0 插入到第一个节点后面。
303+
*/
304+
list.InsertNode(0, 7.0); // 成功:7
305+
list.InsertNode(1, 5.0); // 成功:7 -> 5
306+
list.InsertNode(-1, 5.0); // 失败:index 不能是负数
307+
list.InsertNode(0, 6.0); // 成功:6 -> 7 -> 5
308+
list.InsertNode(8, 4.0); // 失败:index 超出链表长度
309+
310+
// 打印当前链表
311+
list.DisplayList();
312+
313+
// 查找 5.0
314+
if (list.FindNode(5.0) > 0) {
315+
cout << "5.0 found" << endl;
316+
} else {
317+
cout << "5.0 not found" << endl;
318+
}
319+
320+
// 查找 4.5
321+
if (list.FindNode(4.5) > 0) {
322+
cout << "4.5 found" << endl;
323+
} else {
324+
cout << "4.5 not found" << endl;
325+
}
326+
327+
// 删除 7.0
328+
list.DeleteNode(7.0);
329+
330+
// 再次打印链表
331+
list.DisplayList();
332+
333+
return 0;
334+
}
335+
```
336+
________________________________________
337+
2. 例题指引
338+
顺序 题目 难度 对应知识点
339+
1 203. Remove Linked List Elements
340+
Easy 删除指定值节点,对应 DeleteNode
341+
2 83. Remove Duplicates from Sorted List
342+
Easy 遍历链表,删除重复节点
343+
3 876. Middle of the Linked List
344+
Easy 链表遍历,理解 currNode = currNode->next
345+
4 206. Reverse Linked List
346+
Easy 修改 next 指针
347+
5 21. Merge Two Sorted Lists
348+
Easy 连接两个链表

0 commit comments

Comments
 (0)