单链表
结构描述
#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);
//在第Pos个位置插入,若不存在该位置报错
void InsertThisPos(int Pos, DataType X);
//尾删
void PopBack();
//头删
void PopFront();
//删除第Pos位元素,若无该位置,则返回错误
void DeleteThisPos(int Pos);
// 把链表置为空表
void MakeEmpty();
//查找值为 Target的元素,若不存在,则返回空指针,存在则返回节点指针
Node * SearchByValue(DataType Target);
void ModifyByValue(DataType Value, DataType NewValue);
//创建一个空表
void Init();
//判空,若空,则返回true,反之返回false
bool IsEmpty();
//打印链表
void Print();
//分配空间,根据参数X分配空间,分配成功则返回该节点的指针
Node * BuyNode(DataType X);
};
初始化
建立一个空表,即把 Head
指向空。
void SingleLinkedList::Init() {
Head = nullptr;
}
判空
判断链表是否为空,即 Head == nullptr
是否成立。
-
若成立则返回
true
-
否则返回
false
bool SingleLinkedList::IsEmpty() {
return Head == nullptr;
}
打印
-
表空:返回错误
-
非空:从头指针向后遍历,一直遍历到表尾,即
Cur == 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;
//Cur->Next为空时,找到尾节点,退出循环
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;
//把倒数第二个节点指向空指针,Tmp指向尾节点,故其指针域为空指针
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) {
;
}
//退出循环时,不是i == Pos, 就是 Pre == nullptr
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);
}
//非空,删除第0个元素
if (Pos == 0) {
PopFront();
}
else {
//非空,删除第N个元素(N > 0)
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();
}
}
标签:Pre,Node,单链,void,nullptr,Next,节点
From: https://www.cnblogs.com/codels/p/18309480