这里采用了模板方法实现单向链表,总体文件分为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;
}