单向链表
使用虚头结点、结构体、接口(即多态)、类模板实现 单向链表
1.加入 虚头节点 同一 增删 代码逻辑,如图:
2. 自定义数据元素为 struct 结构体,定义、使用、返回、并显示自定义的数据类型:
typedef struct data{
std::string name;
int age;
std::string sex;
float salary;
data(std::string name="", int age=0, std::string sex="", float salary=0.00){
this->name = std::move(name);
this->age = age;
this->sex = std::move(sex);
this->salary = salary;
}
} Data;
注意:
在结构体中引入了 结构体的构造函数,并赋初始值,这样在创建数据的时候不初始化,会使用结构体构造函数默认初始化,也可以通过类型初始化,如:
// Data data1; // 默认初始化
// Data data1=Data(); // 通过 数据类型 默认初始化
Data data1=Data("Gavin", 18, "man", 30000.00);
// Data data1("Gavin", 18, "man", 30000.00);
cout << data1.name << "\t" << data1.age << "\t" << data1.sex << "\t" << data1.salary << endl;
3.多态
定义父类 virtual 成员函数, 子类重写父类虚方法,调用时:定义父类实例,使父类指向子类方法,
注意:虚方法可以没有具体的实现逻辑,但是要有实现。
4.定义节点:
TData,就是自定义的 Data 数据类型,TData是模板类型名:template <classs TData>
typedef struct node{
TData Elements;
node * next;
// 结构体--->构造函数
node(TData Elements= TData(), node* next= nullptr){
this->Elements = Elements;
this->next = next;
}
} Node;
5.代码:
以 模板类 的方式实现的:linkedList.h
#ifndef SIMPLY_LINKEDLIST_LINKEDLIST_STRUCT_H
#define SIMPLY_LINKEDLIST_LINKEDLIST_STRUCT_H
#include <iostream>
#include <utility>
template <typename T>
class Interface{
/* 全部为虚函数*/
public:
virtual ~Interface();
virtual int size() const;
virtual void clear();
virtual bool contains(T& element);
virtual void add(T& element);
virtual void add(T& element, int index);
virtual T get(int index) const;
virtual T set(T& element, int index);
virtual T remove(int index);
virtual int getPos(T& element);
virtual void display() const;
virtual bool equals(T& elems1, T& elems2);
virtual void displaySingleData(const T& tData) const;
};
// 虚函数---> 必须要给出 实现代码(没有具体的实现功能),即便子类已经重写了父类的成员函数;纯虚函数,可以没有实现代码。
template<typename T>
int Interface<T>::size() const {
return 0;
}
template<typename T>
void Interface<T>::clear() {
}
template<typename T>
bool Interface<T>::contains(T &element) {
return false;
}
template<typename T>
void Interface<T>::add(T &element) {
}
template<typename T>
void Interface<T>::add(T &element, int index) {
}
template<typename T>
T Interface<T>::get(int index) const {
return T();
}
template<typename T>
T Interface<T>::set(T &element, int index) {
return T();
}
template<typename T>
T Interface<T>::remove(int index) {
return T();
}
template<typename T>
int Interface<T>::getPos(T &element) {
return 0;
}
template<typename T>
void Interface<T>::display() const {
}
template<typename T>
bool Interface<T>::equals(T &elems1, T &elems2) {
return false;
}
template<typename T>
void Interface<T>::displaySingleData(const T &tData) const {
}
template <typename T>
Interface<T>::~Interface() = default;
// 下面代码为: 子类的具体实现
template <class TData>
class LinkedList_struct : public Interface<TData>{
private:
const int NOT_FOUND = -1;
int Size;
typedef struct node{
TData Elements;
node * next;
// 结构体--->构造函数
node(TData Elements= TData(), node* next= nullptr){
this->Elements = Elements;
this->next = next;
}
} Node;
Node* first;
Node* node(int index) const{
Node* nd = first->next;
for(int i=0; i<index; ++i){
nd = nd->next;
}
return nd;
}
public:
LinkedList_struct();
LinkedList_struct(TData& data, Node* next);
~LinkedList_struct();
int size() const override;
void clear() override;
bool contains(TData& element);
void add(TData& element);
void add(TData& element, int index);
TData get(int index) const;
TData set(TData& element, int index);
TData remove(int index) ;
int getPos(TData& element);
bool equals(TData& tData1, TData& tData2);
void display() const;
void displaySingleData(const TData& tData) const;
};
template <class TData>
LinkedList_struct<TData>::LinkedList_struct():Size(0){
first = new Node();
}
template <class TData>
LinkedList_struct<TData>::LinkedList_struct(TData &data, Node* next):Size(0), Node(data, next){
first = new Node();
}
template <class TData>
LinkedList_struct<TData>::~LinkedList_struct(){
clear();
}
template <class TData>
int LinkedList_struct<TData>::size() const{
return Size;
}
template <class TData>
void LinkedList_struct<TData>::clear(){
Node* node = first;
int cnt = 0;
while(node != nullptr){
auto q = node->next;
delete node;
node = q;
++cnt;
}
Size = 0;
first = nullptr; // 虽然 first 指向的内存被释放了,但是 first 的值并不为空,会导致析构函数死循环或错误退出。
std::cout << "...calling destructor...cnt--->" << cnt << std::endl;
}
template <class TData>
bool LinkedList_struct<TData>::contains(TData &element) {
return getPos(element) != NOT_FOUND;
}
template <class TData>
void LinkedList_struct<TData>::add(TData& element) {
add(element, Size);
}
template <class TData>
void LinkedList_struct<TData>::add(TData& element, int index) {
Node* prev = index==0? first:node(index-1);
prev->next = new Node(element, prev->next);
++Size;
}
template <class TData>
TData LinkedList_struct<TData>::remove(int index) {
Node* prev = index==0? first:node(index-1);
auto old = prev->next;
prev->next = old->next;
TData oldE = old->Elements;
--Size;
return oldE;
}
template <class TData>
TData LinkedList_struct<TData>::get(int index) const {
return node(index)->Elements;
}
template <class TData>
TData LinkedList_struct<TData>::set(TData& element, int index) {
auto ptr = node(index);
TData old = ptr->Elements;
ptr->Elements = element;
return old;
}
template <class TData>
int LinkedList_struct<TData>::getPos(TData &element) {
Node * ptr = first->next;
int pos = NOT_FOUND;
for (int i=0; i < Size; ++i){
if(equals(element,ptr->Elements)){
pos = i;
break;
}
ptr = ptr->next;
}
return pos;
}
template <class TData>
bool LinkedList_struct<TData>::equals(TData &tData, TData &elems2) {
if (tData.name == elems2.name && tData.age == elems2.age && tData.sex == elems2.sex && tData.salary == elems2.salary){
return true;
}else{
return false;
}
}
template <class TData>
void LinkedList_struct<TData>::display() const {
Node* nd = first->next;
std::cout << "name:\t" << "age:\t" << "sex:\t" << "salary:\t" << std::endl;
for (int i=0; i<Size; ++i){
std::cout << nd->Elements.name << "\t" << nd->Elements.age << "\t" << nd->Elements.sex << "\t"
<< nd->Elements.salary << std::endl;
nd = nd->next;
}
}
template <class TData>
void LinkedList_struct<TData>::displaySingleData(const TData& tData) const {
std::cout << tData.name << "\t" << tData.age << "\t" << tData.sex << "\t" << tData.salary << std::endl;
}
#endif //SIMPLY_LINKEDLIST_LINKEDLIST_STRUCT_H
测试代码
#include <iostream>
#include <utility>
#include "linkedList.h"
using std::cout;
using std::endl;
typedef struct data{
std::string name;
int age;
std::string sex;
float salary;
data(std::string name="", int age=0, std::string sex="", float salary=0.00){
this->name = std::move(name);
this->age = age;
this->sex = std::move(sex);
this->salary = salary;
}
} Data;
int main(){
// Data data1;
// Data data1=Data();
Data data1=Data("Gavin", 18, "man", 30000.00);
// Data data1("Gavin", 18, "man", 30000.00);
cout << data1.name << "\t" << data1.age << "\t" << data1.sex << "\t" << data1.salary << endl;
cout << "---------------------------------------------------------------------" << endl;
cout << "---------------------------------------------------------------------" << endl;
Data data2("Evans", 20, "man", 25000);
Data data3("lucy", 25, "girls", 25000);
Data data4("lily", 30, "woman", 2500);
Data data5("Lydia", 28, "man", 65000);
Data data6("sally", 22, "girls", 95000);
Data data7("sam", 27, "man", 150000);
Data data8("Ailsa", 28, "girls", 200000);
Data data9("edison", 32, "man", 300000);
Interface<Data>* lst = new LinkedList_struct<Data>();
// auto lst = new LinkedList_struct<Data>();
// function--->add()
lst->add(data1, 0);
lst->add(data2);
lst->add(data3, lst->size());
lst->add(data4);
lst->add(data5);
lst->add(data6, 3);
lst->add(data7);
lst->add(data8);
lst->add(data9);
lst->display();
cout << "---------------------------------------------------------------------" << endl;
// function--->remove()
lst->remove(0); // 删除 第一个 节点
lst->remove(lst->size()-1); // 删除最后一个 节点
Data tData = lst->remove(3); // 删除 索引为 3 的节点
lst->displaySingleData(tData);
cout << endl;
lst->display();
cout << "---------------------------------------------------------------------" << endl;
// function--->set()
Data data10("Aaron", 23, "man", 631452);
tData = lst->set(data10, 3);
lst->displaySingleData(tData);
cout << endl;
lst->display();
cout << "---------------------------------------------------------------------" << endl;
// function--->get()
tData = lst->get(5);
lst->displaySingleData(tData);
cout << "---------------------------------------------------------------------" << endl;
// function--->getPos()
int pos = lst->getPos(data8);
cout << "pos: " << pos << endl;
// data9 被删除了,试着 获取看是否存在?
pos = lst->getPos(data9);
cout << "pos: " << pos << endl;
cout << "---------------------------------------------------------------------" << endl;
//function--->contains()
bool res = lst->contains(data9);
cout << "result: " << res << endl;
res = lst->contains(data2);
cout << "result: " << res << endl;
cout << "---------------------------------------------------------------------" << endl;
delete lst;
return 0;
}
运行结果:
E:\programme\C_C++\CLion\C++\algorithm\LinkedList\simply_LinkedList\cmake-build-debug\simply_LinkedList.exe
Gavin 18 man 30000
---------------------------------------------------------------------
---------------------------------------------------------------------
name: age: sex: salary:
Gavin 18 man 30000
Evans 20 man 25000
lucy 25 girls 25000
sally 22 girls 95000
lily 30 woman 2500
Lydia 28 man 65000
sam 27 man 150000
Ailsa 28 girls 200000
edison 32 man 300000
---------------------------------------------------------------------
lily 30 woman 2500
name: age: sex: salary:
Evans 20 man 25000
lucy 25 girls 25000
sally 22 girls 95000
Lydia 28 man 65000
sam 27 man 150000
Ailsa 28 girls 200000
---------------------------------------------------------------------
Lydia 28 man 65000
name: age: sex: salary:
Evans 20 man 25000
lucy 25 girls 25000
sally 22 girls 95000
Aaron 23 man 631452
sam 27 man 150000
Ailsa 28 girls 200000
---------------------------------------------------------------------
Ailsa 28 girls 200000
---------------------------------------------------------------------
pos: 5
pos: -1
---------------------------------------------------------------------
result: 0
result: 1
---------------------------------------------------------------------
...calling destructor...cnt--->7
Process finished with exit code 0
注意:
1.共创建了 9 个 Data 结构体数据,调用 remove() 时,删除了 3 个,剩余 6 个节点存储数据
2.最后调用析构函数 7 次:因为 要析构 6个数据节点 + 1个虚头节点