单链表
结构描述
| #include <iostream> |
| #include <cstdlib> |
| |
| using namespace std; |
| |
| typedef int DataType; |
| |
| |
| typedef struct Node { |
| DataType A; |
| struct Node * Next; |
| }Node; |
| |
| class SingleLinkedList { |
| private: |
| Node * Head; |
| public: |
| |
| void PushBack(DataType X); |
| |
| void PushFront(DataType X); |
| |
| void InsertThisPos(int Pos, DataType X); |
| |
| |
| void PopBack(); |
| |
| void PopFront(); |
| |
| void DeleteThisPos(int Pos); |
| |
| void MakeEmpty(); |
| |
| |
| Node * SearchByValue(DataType Target); |
| void ModifyByValue(DataType Value, DataType NewValue); |
| |
| |
| void Init(); |
| |
| bool IsEmpty(); |
| |
| void Print(); |
| |
| Node * BuyNode(DataType X); |
| }; |
初始化
建立一个空表,即把 Head
指向空。
| void SingleLinkedList::Init() { |
| Head = nullptr; |
| } |
判空
判断链表是否为空,即 Head == nullptr
是否成立。
| bool SingleLinkedList::IsEmpty() { |
| return Head == nullptr; |
| } |
打印
| void SingleLinkedList::Print() { |
| |
| if (IsEmpty()) { |
| cout << "List Is Empty!\n"; |
| exit(-1); |
| } |
| |
| Node * Cur = Head; |
| while (Cur != nullptr) { |
| cout << Cur->A << "\n"; |
| Cur = Cur->Next; |
| } |
| } |
创建节点
根据参数 X
,创建一个数据域为 X
,指针域为空的节点 NewNode
并返回
| Node * SingleLinkedList::BuyNode(DataType X) { |
| |
| Node * NewNode = (Node *)malloc(sizeof (Node)); |
| if (NewNode == nullptr) { |
| cout << "Malloc Failed!" << "\n"; |
| exit(-1); |
| } |
| |
| |
| NewNode->A = X; |
| NewNode->Next = nullptr; |
| |
| return NewNode; |
| } |
头插
- 分配节点
NewNode
;
- 把节点的指针域指向当前头节点,即
NewNode->Next = Head
;
- 把头指针
Head
指向 NewNode
| void SingleLinkedList::PushFront(DataType X) { |
| Node * NewNode = BuyNode(X); |
| NewNode->Next = Head; |
| Head = NewNode; |
| } |
尾插
- 若表空:
- 分配节点;
- 把头指针指向该节点;
- 表非空:
- 遍历,找到尾节点
- 分配节点,并把节点接在尾节点之后
| void SingleLinkedList::PushBack(DataType X) { |
| |
| if (IsEmpty()) { |
| Head = BuyNode(X); |
| } |
| |
| else { |
| Node * Cur = Head; |
| |
| while (Cur->Next != nullptr) { |
| Cur = Cur->Next; |
| } |
| |
| Node * NewNode = BuyNode(X); |
| Cur->Next = NewNode; |
| } |
| } |
头删
- 表空:报错
- 非空:
- 用临时变量
Tmp
存放头节点;
- 把头节点向后移动一位,即
Head = Head->Next
;
- 释放
Tmp
并置空,防止指针悬空
| void SingleLinkedList::PopFront() { |
| |
| if (IsEmpty()) { |
| cout << "List Is Empty!\n"; |
| exit(-1); |
| } |
| |
| |
| Node * Tmp = Head; |
| Head = Head->Next; |
| free(Tmp); |
| Tmp = nullptr; |
| } |
尾删
- 表空:报错
- 非空:
- 只有一个节点:直接置空即可
- 有多个节点:
- 找到倒数第二个节点
Cur
;
- 用临时变量保存尾节点,即
Tmp = Cur->Next
;
- 把
Cur
的指针域指向 nullptr
- 释放
Tmp
| void SingleLinkedList::PopBack() { |
| |
| if (IsEmpty()) { |
| cout << "List Is Empty!\n"; |
| exit(-1); |
| } |
| |
| |
| if (Head->Next == nullptr) { |
| free(Head); |
| Head = nullptr; |
| } |
| |
| else { |
| Node * Cur = Head; |
| |
| while (Cur->Next->Next != nullptr) { |
| Cur = Cur->Next; |
| } |
| |
| Node * Tmp = Cur->Next; |
| |
| Cur->Next = Tmp->Next; |
| |
| free(Tmp); |
| Tmp = nullptr; |
| } |
| } |
插入元素
在 Pos
处插入元素(模拟数组下标,从0开始计数)
- 若存在该位置,则插入元素
- 若
Pos
为0,即在链表头插入,直接调用头插方法
- 若
Pos
大于0,则遍历链表,循环变量 i
从 1
开始,考虑下标为 1
到尾的节点
- 用
Pre
变量存放 第 i - 1
号位的节点指针,循环条件为 i < Pos && Pre != nullptr
,如果 Pre
为空,即指向了链表的最后,若此时 i != Pos
,则下存在,返回错误
- 若
i == Pos
,则该位置存在,直接分配节点并插入即可 。有点双指针的意思
- 不存在该位置,则返回错误;
| void SingleLinkedList::InsertThisPos(int Pos, DataType X) { |
| if (Pos == 0) { |
| PushFront(X); |
| } |
| else { |
| int i; |
| Node * Pre; |
| for (i = 1, Pre = Head; i < Pos && Pre != nullptr; i++, Pre = Pre->Next) { |
| ; |
| } |
| |
| if (Pos == i && Pre != nullptr) { |
| Node * NewNode = BuyNode(X); |
| NewNode->Next = Pre->Next; |
| Pre->Next = NewNode; |
| } |
| else { |
| cout << Pos << " Posiont is not exist!\n"; |
| exit(-1); |
| } |
| } |
| } |
删除元素
- 表空:报错
- 非空:
- 删除第0个元素时,直接调用头删方法
- 有多个元素时:
- 和插入一样,用一个
Pre
指针指向要删除元素的前一位,即 Pre = Head, i = 1
- 遍历链表,直至
i == Pos || Pre->Next == nullptr
时退出循环,Pre->Next == nullptr
时,说明要删除的元素是尾指针的指针域,即空指针,这显然是错误的,所以可以以此来作为遍历的出口条件
- 若第
Pos
个元素存在,则删除该元素
| void SingleLinkedList::DeleteThisPos(int Pos) { |
| |
| if (IsEmpty()) { |
| cout << "List Is Empty!\n"; |
| exit(-1); |
| } |
| |
| |
| if (Pos == 0) { |
| PopFront(); |
| } |
| else { |
| |
| int i = 0; |
| Node * Pre = nullptr; |
| for (i = 1, Pre = Head; Pre->Next != nullptr && i < Pos; i++, Pre = Pre->Next) { |
| ; |
| } |
| |
| if (i == Pos && Pre->Next != nullptr) { |
| Node * Tmp = Pre->Next; |
| Pre->Next = Tmp->Next; |
| free(Tmp); |
| Tmp = nullptr; |
| } |
| else { |
| cout << Pos << " Position is not exist!\n"; |
| } |
| } |
| |
| } |
根据值查找元素
- 表空:返回错误
- 非空:遍历链表,逐一比较,直到第一个与目标值相等的元素时,返回该节点的指针。若直至表尾仍未发现该元素,则返回一个空指针。
| Node * SingleLinkedList::SearchByValue(DataType Target) { |
| if (IsEmpty()) { |
| cout << "List Is Empty!\n"; |
| exit(-1); |
| } |
| |
| Node * Cur = Head; |
| while (Cur != nullptr) { |
| if (Cur->A == Target) { |
| return Cur; |
| } |
| Cur = Cur->Next; |
| } |
| |
| return nullptr; |
| } |
修改链表元素值
- 查找:
- 修改:根据查找到的结果修改;
- 查找返回空:给出提示消息,并退出程序
- 查找返回元素节点指针:修改该元素的值
| void SingleLinkedList::ModifyByValue(DataType Target, DataType NewValue) { |
| Node * Ret = SearchByValue(Target); |
| if (Ret == nullptr) { |
| cout << "The Target Is Not Exist!\n"; |
| exit(-1); |
| } |
| |
| Ret->A = NewValue; |
| } |
摧毁
| void SingleLinkedList::MakeEmpty() { |
| if (IsEmpty()) { |
| cout << "List Is Empty!\n"; |
| exit(-1); |
| } |
| |
| while (!IsEmpty()) { |
| PopFront(); |
| } |
| } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!