基于C++的单向链表实现(使用模板)

这里采用了模板方法实现单向链表,总体文件分为linklist.hpp文件以及链表.cpp文件
在这里插入图片描述
使用模板进行分文件编写时,与普通的类文件编写会有一些区别。
解决方法1.在主文件中导入.cpp文件(但是这样一般会很怪)
解决方法2.将.cpp文件复制到.h文件中,然后将.h文件更名为.hpp文件
在这里使用的是第二种方案即将.h文件命名为.hpp
链表节点类

#pragma once
#include <iostream>
using namespace std;
template<class T>
class LinkNode  //定义链表节点
{
public:
	T data;  //每个节点由数据 和指针构成
	LinkNode<T>* next;
	LinkNode<T>(){}; 默认构造函数
};

链表类

class LinkList
{
public:
	LinkList();
	LinkList(const LinkList<T>& linklist);  //拷贝构造函数
	LinkList* Init_linklist();  //用于初始化链表头与链表大小
	void Insert_linklist(int pos, T vaule);//插入数据
	LinkNode<T>* first_node();//读取链表的第一个值
	void remove_by_pos(int pos);//删除某个位置的数据
	void Free_linklist();//是释放链表
	int find_linklist(T vaule);//找某个元素 感觉如果不是默认类型需要进行重写。
	void print_linklist(void (*print)(T));  //传入的是函数指针   返回值类型 (*名称)(数据类型)

public:
	int size;//链表大小
	LinkNode<T>* Head;//链表头
	LinkList* list;  
};

构造函数

template<class T>
LinkList<T>::LinkList() {
}
template <class T>
LinkList<T>::LinkList(const LinkList<T>& linklist)//拷贝构造函数 {
	if (this->list != NULL)
	{
		this->Free_linklist();
	}
	LinkList<T> newlist = new LinkList<T>(this->size);//开辟内存空间
	this->list = newlist;//将list修改为新的空间
	memcpy(this->list, linklist, sizeof(linklist));//复制
	this->size = linklist.size;//复制大小
	this->Head = linklist.Head;//复制头节点
	return *this;//返回对象的指针
}

初始化函数:目的将头节点接入到链表中

template<class T>
LinkList<T>* LinkList<T>::Init_linklist()
{
	LinkList* list = new LinkList;//创建链表
	list->size = 0;
	//头节点不保存数据信息
	//LinkNode<T> *head;
	LinkNode<T> *head = new LinkNode<T>;//创建节点
	list->Head = head;//将头节点接入 到链表
	list->Head->next = NULL;//将指针域设为空
	this->list = list;
	return list;
}

插入数据

template<class T>
void LinkList<T>::Insert_linklist(int pos, T vaule) {
	
	if (pos < 0 || pos > this->size)//判定位置
	{
		pos = this->list->size;//如果越界将插入到最后的位置
	}
	LinkNode<T>* node = new LinkNode<T>;  //1 创建一个新的节点
	node->data = vaule;
	node->next = NULL;  //先令节点为空  然后放入链表中
	//2 找节点
	LinkNode<T>* pCurrent = this->list->Head;
	for (int i = 0; i < pos; i++) {
		pCurrent = pCurrent->next;
	}
	//3 更换节点  先连接后边的节点 再接前边的节点
	node->next = pCurrent->next;
	pCurrent->next = node;
	this->size += 1;//链表大小加1
}

按位置删除节点

template<class T>
void LinkList<T>::remove_by_pos(int pos) {
	if (pos < 0 || pos >= this->size)
	{
		return;
	}
	LinkNode<T>* pcurrent = this->list->Head;
	for (int i = 0; i < pos; i++)
	{
		pcurrent = pcurrent->next;
	}
	LinkNode<T>* delnode = pcurrent->next;
		pcurrent->next = delnode->next;
	delete delnode;
	this->size -= 1;
}

找到值返回pos :注意如果是自己定义的数据类型需要重新写此函数


template<class T>
int LinkList<T>::find_linklist(T vaule) {
	int pos = -1;
	LinkNode<T>* pcurrent = this->list->Head->next;
	for (int i = 0; i < this->size; i++)
	{
		if (pcurrent->data == vaule)
		{
			pos = i;
			break;
		}
		pcurrent = pcurrent->next;
	}
	return pos;
}

返回第一个节点也就是头节点的下一个节点

LinkNode<T>* LinkList<T>::first_node() {
	return this->list->Head->next;
}

打印数据 这里使用了函数指针 自定义一个print函数

void LinkList<T>::print_linklist(void(*print)(T)) {
	if (this->list == nullptr) {
+		return;
	}
	LinkNode<T>* pcurrent = this->list->Head->next;
	for (size_t i = 0; i < this->size; i++)
	{
		print(pcurrent->data);
		pcurrent = pcurrent->next;
	}
}

释放链表

void LinkList<T>::Free_linklist() {
	LinkNode<T>* pcurrent = this->list->Head;
	while (pcurrent != NULL)
	{
		LinkNode<T>* pnext = pcurrent->next;
		delete pcurrent;
		pcurrent = pnext;
	}
	delete this->list;
	this->list = nullptr;
	this->size = 0;
}

主函数:
当使用c++的数据类型时

void print(int a) {
	cout << a<< endl;
}
	lis.Init_linklist();
	lis.Insert_linklist(0, 1);
	lis.Insert_linklist(0, 2);
	lis.Insert_linklist(0, 3);
	lis.Insert_linklist(0, 4);
	int pos = lis.find_linklist(3);
	cout << pos << endl;
	lis.print_linklist(print);

当使用自定义数据类型时

#include <iostream>
#include "LinkList.hpp"
#include <string>
using namespace std;
class Person
{
public:
	Person() {};
	Person(string name, int age) {
		this->name = name;
		this->age = age;
		next = NULL;
	}
	string name;
	int age;
	Person* next;

};
void print(Person a) {
	cout << "年龄" << a.age << endl;
}
int main() {
	Person p1 = { "aa", 10 };
	Person p2("bb", 11);
	Person p3("cc", 12);
	Person p4("dd", 13);
	
	LinkList<Person> lis;
	lis.Init_linklist();
	lis.Insert_linklist(0, p1);
	lis.Insert_linklist(0, p2);
	lis.Insert_linklist(0, p3);
	lis.Insert_linklist(0, p4);
	
	Person* res = (Person*)lis.first_node();
	cout << res->age << res->name << endl;
	
	lis.remove_by_pos(1);
	//lis.Free_linklist();
	cout << lis.size << endl;
	//验证拷贝构造函数
	LinkList<Person> lis2;
	lis2 = lis;
	cout << lis2.size << endl;
	lis2.print_linklist(print);
	cout << lis.size << endl;
	system("pause");
	return 0;



}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值