//list.h
#pragma once
template<typename T>class slistNode
{
public:
slistNode() { next = nullptr; cout << "调用了slistnode的构造函数" << endl; }
~slistNode() {delete next;cout << "调用了slistnode的析构函数" << endl;};
T data;
slistNode* next;
};
template<typename T>
class myslist
{
private:
unsigned int listlength;
slistNode<T>* headnode;
public:
myslist();//初始化
~myslist();//用于删除lastnode,headnode。他们动态分配了内存
unsigned int length();//链表元素的个数
bool add(int n);//在链表的头部插入节点
void traversal();//遍历整个链表并打印
bool isEmpty();//判断链表是否为空
slistNode<T>* find(T x);//查找第一个值为x的节点,返回节点的地址,找不到返回NULL
void Delete(T x);//删除第一个值为x的节点
bool insert(T x,int n);//在第n个节点后插入值为x的节点
bool insertlast(T x);//在链表的尾部插入节点
};
template<typename T>
myslist<T>::~myslist()
{
delete headnode;
cout << "调用的myslist的析构函数" << endl;
}
template<typename T>
myslist<T>::myslist()
{
cout << "调用的myslist的构造函数" << endl;
headnode = new slistNode<T>();//这里调用默认构造函数,所以head->next=nullptr;如果有形参,则调用对应的构造函数。
headnode->data = 0;
listlength = 0;
}
template<typename T>
unsigned int myslist<T>::length()
{
return listlength;
}
template<typename T>
bool myslist<T>::add(int n)
{
int i = 0;
for (i; i < n; i++)
{
cout << "请输入你想插入的第" <<n-i << "个数据";
T data1;
cin >> data1;
cout << endl;
//下面这个动态指针分配了地址的,这样每次后生成的位置都会指向在它之前生成的那个节点的指针域。
slistNode<T>* node = new slistNode<T>();
if (node == nullptr)
{
cout << "动态内存分配失败" << endl;
return 0;
}
//每次头节点指向的位置都是上一次循环生成的节点的地址,这使得每个节点都是在头节点后面插入的。
node->next = headnode->next;
node->data = data1;
headnode->next=node;
}
listlength = listlength + n;
return 1;
}
template<typename T>
void myslist<T>::traversal()
{
if (headnode->next == nullptr)
cout << "该链表的长度为0" << endl;
else
{
slistNode<T>* node = headnode;
while (node->next != nullptr)
{
cout << "链表中的数据为" << ": "<<node->next->data<<endl;
node = node->next;
}
cout << "\n输出完毕" << endl;
}
}
template<typename T>
bool myslist<T>::isEmpty()
{
if (headnode->next == nullptr)
{
cout << "链表已经空了" << endl;
return true;
}
else
{
cout << "链表非空" << endl;
return false;
}
}
template<typename T>
void myslist<T>::Delete(T x)
{
slistNode<T>* node= headnode;
while (node->next != nullptr)
{
if (node->next->data == x)
{
slistNode<T>* node1 = node->next;
node1 = node->next;
node->next = node1->next;
listlength = listlength - 1;
}
else
node = node->next;
}
cout << "该链表没有该值" << endl;
}
template<typename T>
bool myslist<T>::insert(T x,int n)
{
slistNode<T>* node = new slistNode<T>();
if (node == nullptr)
{
cout << "动态内存分配失败" << endl;
return 0;
}
node->next = headnode->next;//注意:这里将node=headnode是错误的,后者是将指针headnode赋给node,这会导致node与headnode指向同一个内存,
//使得原先分配给node的内存泄漏,同时,导致travel时,由于headnode地址和Node一样,从而headnode->next==headnode
if (n < 0)
{
cout << "你输入的位置不合理" << endl;
return 0;
}
else if (n == 0)
{
node->data = x;
headnode->next = node;
return 1;
}
else if (n > listlength)
{
cout << "你输入的位置超过链表的长度" << endl;
return 0;
}
else if (0 < n&&n < listlength)
{
if (node->next == nullptr)
{
cout << "你输入的位置不合理" << endl;
return 0;
}
else
{
slistNode<T>* node1 = headnode;
int i = 0;
while (i < n)
{
node1 = node1->next;//不要给指向新节点的指针重新赋值,这回改变指针的地址,从而创建新节点的意图会失败。使用中间指针
i++;
}
node->next = node1->next;
node1->next = node;
node->data = x;
return 1;
}
}
}
template<typename T>
bool myslist<T>::insertlast(T x)
{
slistNode<T>* node = new slistNode<T>();
if (node == nullptr)
{
cout << "动态内存分配失败" << endl;
return 0;
}
if (headnode->next == nullptr)
{
headnode->next = node;
node->data = x;
}
else
{
slistNode<T>* node1 = headnode;
while (node1->next != nullptr)
{
node1 = node1->next;
}
node1->next = node;
node->data = x;
listlength = listlength + 1;
}
}
template<typename T>
slistNode<T>* myslist<T>::find(T x)
{
slistNode<T>* node =headnode;
if (node->next == nullptr)
{
cout << "该链表没有值:" << x<<endl;
}
else
{
int i = 0;
while (node->next != nullptr)
{
i = i + 1;
if (node->next->data == x)
{
cout << "链表中该值是第:" << i << "个位置" << endl;
cout << "它的地址为:" << node << endl;
return node;
}
else
node = node->next;
}
cout << "该链表没有值:" << x << endl;
}
}
//1,使用new动态分配内存的指针对象,不手动释放内存时,是不会调用析构函数的,但如果该类的对象是包含在另一个对象里面,则当另一个对象生命结束时,
//则会先调用该类的对象析构函数,再调用另一个对象的析构函数。
//2,将一个对象指针赋值为空,还是分配了内存的
//3,在对象释放之前,不要将其对应的指针赋值新指针。这会使得内存泄漏
//main.cpp
#include"List2.h"
#include<iostream>
using namespace std;
int main()
{
{
myslist<int> list;
list.isEmpty();
cout << "链表的长度为:" << list.length() << endl;
int n;
cout << "请输入链表首部插入数据的个数:";
cin >> n;
cout << endl;
list.add(n);
list.traversal();
list.isEmpty();
cout << "链表的长度为:" << list.length() << endl;
cout << "请输入你想要在链表中寻找的值:";
int n1;
cin >> n1;
cout << endl;
slistNode<int>* b=list.find(n1);
list.Delete(n1);
cout << "在删除值:" << n1 << "后,链表的中的值为:";
list.traversal();
int m, n2;
cout << "请输入你想插入链表中值的大小:";
cin >> m;
cout << endl;
cout << "请输入你想插入链表中值的位置";
cin >> n2;
cout << endl;
list.insert(m,n2-1);
cout << "在插入新值"<<m<<"后,链表中的值为";
list.traversal();
int x;
cout << "请输入你想在链表尾部插入值的大小:";
cin >> x;
cout << endl;
list.insertlast(x);
list.traversal();
}
system("pause");
return 0;
}
菜鸟一只