一.链表节点
1.链表节点的定义
#include<iostream>
using namespace std;
class LinkNode
{
public:
int Data;
LinkNode* Next;
LinkNode(int val);
LinkNode();
};
2.链表节点的实现
将新节点的next指针设为null
#include "LinkNode.h"
LinkNode::LinkNode(int val)
:Data(val),Next(nullptr)
{
}
LinkNode::LinkNode()
:Next(nullptr)
{
}
二.单链表实现
1.链表接口
#include<iostream>
#include"LinkNode.h"
using namespace std;
class LinkList
{
private:
LinkNode* Head;//头节点
LinkNode* Curr;//当前节点
LinkNode* Tail;//尾节点
int Size;
public:
LinkList();
void BuildListByHeadInsert(int ele);//头插法建表
void BuildListByTailInsert(int ele);//尾插法建表
void BackwardInsert(int ele);// 在当前节点的后一个节点插入一个新节点
void ForwardInsert(int ele);// 在当前节点(当前节点位于表的中间时)的前一个节点插入一个新节点
void BackwardInsertByNode(int ele,LinkNode* Node);// 在已知节点的后一个节点插入一个新节点
void ForwardInsertByNode(int ele, LinkNode* Node);// 在已知节点的前一个节点插入一个新节点
int getSize();//获取表长
bool isEmpty();//判空
void Delete();//删除当前节点的下一个节点
void DeleteByNode(LinkNode* Node);//删除已知节点的下一个节点
int getCurr();//获取当前节点的数据
void Print();//打印链表
int Find(int ele);//按值查找节点
int At(int pos);//按位置查找节点
void Prev();//将当前节点后移一位
void Clear();//清空链表内元素但不删除
void Destory();//销毁链表
int getTail();//获取尾节点
LinkNode* GetElemByPos(int pos);//按位置查找节点
LinkNode* GetElemByValue(int ele);//按值查找节点
LinkNode* GetHead();//获取头节点
void setTail();//在建表时设置尾节点
int caculateSize();//计算链表长
};
2.初始化
1.创建一个新节点设为头节点
2.将尾节点设为头节点
LinkList::LinkList()
:Size(0)
{
Head = new LinkNode;
Curr = Head;
Tail = Head;
}
3.建表操作
Ⅰ.头插法
每次将节点插入到链表的表头的前一个节点,生成的节点次序和输入数据相反
1.将新节点和头节点的后一个节点联系
2.将头节点和新节点联系
3.若新节点的下一个节点为空节点则将新节点设为尾节点
void LinkList::BuildListByHeadInsert(int ele)
{
Size++;
LinkNode* Temp = new LinkNode(ele);
Temp->Next = Head->Next;//和头节点的后一个节点联系
Head->Next = Temp;//和头节点联系
//setTail();
if (Temp->Next == nullptr)
{
Tail = Temp;
}
}
Ⅱ.尾插法
每次将节点插入到链表的表头的后一个节点,生成的节点次序和输入数据相同
1.将新节点和尾节点联系
2.将新节点设为尾节点
3.将尾节点的下一个节点设为空节点
void LinkList::BuildListByTailInsert(int ele)
{
Size++;
LinkNode* Temp = new LinkNode(ele);
if (Tail->Next == nullptr)
{
Tail->Next = Temp;//和尾节点联系
Tail = Temp;//将新节点设为尾节点
Tail->Next = nullptr;//将尾节点的下一个节点设为空
}
}
4.插入操作
Ⅰ.后插法
1.新节点的next指针指向被插入位置的指针的下一个指针
2.被插入位置的指针的下一个指针设为新指针
3.若新节点的下一个指针为空,设为尾节点
void LinkList::BackwardInsert(int ele)
{
Size++;
LinkNode* Temp = new LinkNode(ele);
Temp->Next = Curr->Next;
Curr->Next = Temp;
if (Temp->Next == nullptr)Tail = Temp;
}
Ⅱ.前插法
在后插法的基础上交换元素
void LinkList::ForwardInsert(int ele)
{
Size++;
LinkNode* Temp = new LinkNode(ele);
Temp->Next = Curr->Next;
Curr->Next = Temp;
swap(Temp->Data, Curr->Data);
}
5.删除操作
1.设被删除节点为删除位置的后一个节点
2.将删除位置的下一个节点和被删除节点的下一个节点相连
3.将节点删除
4.若删除位置的后一个节点为空,将删除位置设置为尾节点
void LinkList::Delete()
{
Size--;
LinkNode* Temp = Curr->Next;
Curr->Next = Temp->Next;
delete Temp;
if (Curr->Next == NULL)Tail = Curr;
}
6.查找操作
1.按值查找
LinkNode* LinkList::GetElemByValue(int ele)
{
LinkNode* Temp = Head->Next;
while (Temp != NULL && Temp->Data != ele)
Temp = Temp->Next;
return Temp;
}
2.按位置查找
LinkNode* LinkList::GetElemByPos(int pos)
{
if (pos < 1)return NULL;
LinkNode* Temp = Head->Next;//头节点的下一个节点可以视为数组下标为1
int j = 1;
while (Temp != NULL && j < pos)
{
Temp = Temp->Next;
j++;
}
return Temp;
}
7.其他操作
1.判空
bool LinkList::isEmpty()
{
//return Size==0;
return Head->Next == nullptr;
}
2.清空链表
1.头节点的下一节点视为数组下标为1
2.遍历链表,但循环中要保存要删除节点中的后驱节点
3.移动节点
4.将头节点的下一节点设为空指针
void LinkList::Clear()
{
if (Head->Next == nullptr)//若为空表
return;
else
{
LinkNode* Temp = Head->Next;//头节点的下一节点视为数组下标为1
while (Temp != nullptr)
{
LinkNode* Temp_Next = Temp->Next;//保存要删除节点的后驱节点
delete Temp;//删除节点
Temp = Temp_Next;//移动被删除节点
}
Head->Next = nullptr;//
Size = 0;
}
}
3.销毁链表
1.判断是否为空表
2.清空链表
3.删除头节点,将头节点设为空节点
void LinkList::Destory()
{
if (Head->Next == nullptr)//若为空表
{
return;
}
else
{
this->Clear();
delete Head;
Head = nullptr;
cout << "Successful Destory" << endl;
}
}
4.计算链表长度
1.将头指针看作数组下标为1
2.遍历链表直到链表的下一个节点为空节点
3.Temp = Temp->Next;等价于a++
int LinkList::caculateSize()
{
int length = 0;
LinkNode* Temp = Head->Next;
while (Temp)
{
length++;
Temp = Temp->Next;
}
return length;
}
5.设置尾节点
void LinkList::setTail()
{
LinkNode* Temp = Head;
while (Temp->Next != nullptr)
{
Temp = Temp->Next;
}
Tail = Temp;
}
三。测试函数
#include"LinkList.h"
#include<iostream>
#include<random>
using namespace std;
int main()
{
LinkList Test;
cout << (Test.isEmpty() ? "Test表为空" : "Test表不为空") << endl;
int time;
cout << "输入元素个数为:";
cin >> time;
random_device rd;
mt19937 gen(rd());
uniform_int_distribution<> dis(1, 10);
for (int i = 0; i < time; i++)
{
int ele;
ele = dis(gen);
//cin >> ele;
Test.BuildListByHeadInsert(ele);
}
Test.Print();
cout << endl;
cout << Test.getTail() << endl;
LinkNode* Temp1 = Test.GetElemByPos(5);
Test.BackwardInsertByNode(10,Temp1);
Test.Print();
cout << Test.getTail() << endl;
LinkNode* Temp2 = Test.GetElemByPos(5);
Test.DeleteByNode(Temp2);
Test.Print();
cout << Test.getTail() << endl;
}