链表(一)单链表

一.链表节点

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;
}

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值