-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSLinkList.cpp
373 lines (328 loc) · 8.05 KB
/
SLinkList.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
/* 使用C++复刻单向链表 */
#include <cassert>
#include <cstdio>
#include <iostream>
#include <new>
#define DEBUG
#define SLTdatatype int
/**
* @brief 链表节点结构体
*
* @warning 要使用指针,不能使用引用,因为引用不能使用nullptr
*/
struct SLTNode
{
SLTdatatype data;
SLTNode* next;
/* 构造函数 */
SLTNode(SLTdatatype x) : data(x), next(nullptr) {}
};
/**
* @brief 单向链表类
*/
class SLinkList
{
public:
SLTNode* head; // 头指针
/* 构造函数 */
SLinkList() : head(nullptr) { std::cout << "Single Link List Constructed Successfully" << std::endl; }
/* 析构函数 */
~SLinkList();
/* 头插新节点 */
void push_front(SLTdatatype x);
/* 尾插新节点 */
void push_back(SLTdatatype x);
/* 指定元素前插入 */
void insert_before(SLTdatatype val, SLTdatatype x);
/* 指定元素后插入 */
void insert_after(SLTdatatype val, SLTdatatype x);
/* 头删节点 */
void pop_front(void);
/* 尾删节点 */
void pop_back(void);
/* 打印链表 */
void print(void) const;
};
/**
* @brief 单链表析构函数
*
*/
SLinkList::~SLinkList()
{
SLTNode* node = head;
while (node != nullptr)
{
SLTNode* tempNode = node;
node = node->next;
delete tempNode;
}
#ifdef DEBUG
std::cout << "Single Link List Destructed Successfully" << std::endl;
#endif
}
/**
* @brief 单链表头插节点函数
*
* @param x SLTdatatype 新节点存储的值
*/
void SLinkList::push_front(SLTdatatype x)
{
// 异常处理
// 当抛出异常之后 会中断作用域内的剩余代码
try
{
// 申请节点空间
SLTNode* node = new SLTNode(x);
// 将申请的节点的下一个节点改为当前链表的头
node->next = head;
// 将链表的头改为新申请的节点
head = node;
}
// 异常处理
catch (std::bad_alloc &e)
{
std::cerr << "Memory allocation failed: " << e.what() << std::endl;
exit(1);
}
}
/**
* @brief 单链表尾插节点函数
*
* @param x SLTdatatype 新节点存储的值
*/
void SLinkList::push_back(SLTdatatype x)
{
// 异常处理
// 当抛出异常之后 会中断作用域内的剩余代码
try
{
// 申请节点空间
SLTNode* node = new SLTNode(x);
SLTNode* tailnode = head;
// 如果链表为空 则直接插入
if (tailnode == nullptr)
{
head = node;
}
// 如果链表不为空 则寻找尾节点
else
{
while (tailnode->next != nullptr)
{
tailnode = tailnode->next;
}
// 将尾节点的下一个节点改为新申请的节点
tailnode->next = node;
}
}
// 异常处理
catch (std::bad_alloc &e)
{
std::cerr << "Memory allocation failed: " << e.what() << std::endl;
exit(1);
}
}
/**
* @brief 单链表指定元素前插入
*
* @param val 指定元素的值
* @param x 新节点存储的值
*/
void SLinkList::insert_before(SLTdatatype val, SLTdatatype x)
{
// 判断链表是否为空
if (head == nullptr)
{
perror("head is nullptr, can't insert");
exit(1);
}
// 特殊情况:插入到头节点之前
if (head->data == val)
{
try
{
SLTNode* node = new SLTNode(x);
node->next = head;
head = node;
}
catch (std::bad_alloc &e)
{
std::cerr << "Memory allocation failed: " << e.what() << std::endl;
exit(1);
}
return;
}
// 找到需要插入的元素的前一个节点
SLTNode* prevNode = head;
while (prevNode->next != nullptr && prevNode->next->data != val)
{
prevNode = prevNode->next;
}
// 如果找到指定节点
if (prevNode->next != nullptr)
{
// 插入新节点
try
{
SLTNode* node = new SLTNode(x);
// 新节点指向需要插入的元素
node->next = prevNode->next;
// 需要插入的元素的前一个元素指向新节点
prevNode->next = node;
}
// 异常处理
catch (std::bad_alloc &e)
{
std::cerr << "Memory allocation failed: " << e.what() << std::endl;
exit(1);
}
}
// 没有找到指定节点
else
{
std::cout << "data not fount, insert failed" << std::endl;
}
}
/**
* @brief 单链表指定元素后插入
*
* @param val 指定元素的值
* @param x 新节点存储的值
*/
void SLinkList::insert_after(SLTdatatype val, SLTdatatype x)
{
// 判断链表是否为空
if (head == nullptr)
{
perror("head is nullptr, can't insert");
exit(1);
}
// 找到需要插入的元素
SLTNode* node = head;
while (node != nullptr && node->data != val)
{
node = node->next;
}
// 如果找到指定节点
if (node != nullptr)
{
// 插入新节点
try
{
SLTNode* newNode = new SLTNode(x);
// 新节点指向需要插入的元素的下一个节点
newNode->next = node->next;
// 需要插入的元素指向新节点
node->next = newNode;
}
// 异常处理
catch (std::bad_alloc &e)
{
std::cerr << "Memory allocation failed: " << e.what() << std::endl;
exit(1);
}
}
// 没有找到指定节点
else
{
std::cout << "data not fount, insert failed" << std::endl;
}
}
/**
* @brief 单链表头删函数
*
*/
void SLinkList::pop_front(void)
{
// 判断链表是否为空
if (head == nullptr)
{
perror("head is nullptr, can't pop");
exit(1);
}
/* 删除头节点 */
// 保存头节点的下一个节点
SLTNode* tempNode = head->next;
// 释放头节点
delete head;
// 更改链表头节点
head = tempNode;
}
/**
* @brief 单链表尾删函数
*
*/
void SLinkList::pop_back(void)
{
// 判断链表是否为空
if (head == nullptr)
{
perror("head is nullptr, can't pop");
exit(1);
}
// 如果只有一个节点 则直接删除
if (head->next == nullptr)
{
delete head;
head = nullptr;
}
// 如果有多个节点 则找到尾节点的前一个节点 并删除尾节点
else
{
SLTNode* prevTail = head;
while (prevTail->next->next != nullptr)
{
prevTail = prevTail->next;
}
delete prevTail->next;
// 尾节点的下一个节点置为nullptr
prevTail->next = nullptr;
}
}
/**
* @brief 打印单链表
*
*/
void SLinkList::print(void) const
{
SLTNode* node = head;
while (node != nullptr)
{
std::cout << node->data << "->";
node = node->next;
}
std::cout << "nullptr" << std::endl;
}
int main()
{
// 创建链表对象
SLinkList list;
// 测试头插
list.push_front(10);
list.push_front(20);
list.push_front(30);
std::cout << "After push_front operations: ";
list.print(); // 30->20->10->nullptr
// 测试尾插
list.push_back(40);
list.push_back(50);
std::cout << "After push_back operations: ";
list.print(); // 30->20->10->40->50->nullptr
// 测试指定元素前插入
list.insert_before(10, 25);
std::cout << "After insert_before operation: ";
list.print(); // 30->20->25->10->40->50->nullptr
// 测试指定元素后插入
list.insert_after(10, 35);
std::cout << "After insert_after operation: ";
list.print(); // 30->20->25->10->35->40->50->nullptr
// 测试头删
list.pop_front();
std::cout << "After pop_front operation: ";
list.print(); // 20->25->10->35->40->50->nullptr
// 测试尾删
list.pop_back();
std::cout << "After pop_back operation: ";
list.print(); // 20->25->10->35->40->nullptr
return 0;
}