1.双链表
Line_Table_ADT.h
#pragma once
#ifndef LINE_TABLE_ADT_H
#define LINE_TABLE_ADT_H
//抽象基类
template <typename T>
class List
{
public:
typedef T Value_Type;
typedef T* Value_Pointer;
typedef T& Value_Reference;
typedef const T& Const_Value_Reference;
private:
void operator= (const List&) {}
List(const List&) {}
public:
//构造函数
List() {}
//析构函数
virtual ~List() {}
//纯虚函数子类必须去继承它吗?
//清空线性表
virtual void clear() = 0;
//在当前位置插入
virtual void insert(Const_Value_Reference element) = 0;
//在线性表末尾添加
virtual void append(Const_Value_Reference element) = 0;
//移除当前位置的元素
virtual Value_Type remove() = 0;
//当前位置的前一个元素
virtual void prev() = 0;
//当前位置的下一个元素
virtual void next() = 0;
//线性表的长度
virtual int length() const = 0;
//当前位置
virtual int currPos() const = 0;
//当前位置元素的值
virtual Const_Value_Reference getValue() = 0; //思考返回一个常引用有什么好处?
//移动到指定位置
virtual void moveToPosition(int position) = 0;
};
#endif
Doubly_Link_List_Node.h
#pragma once
#ifndef DOUBLY_LINK_LIST_NODE
#define DOUBLY_LINK_LIST_NODE
template <typename T>
class Doubly_Link_List_Node
{
public:
typedef T Value_Type;
typedef T& Value_Reference;
typedef const T& Const_Value_Reference;
typedef T* Value_Pointer;
typedef Doubly_Link_List_Node Node;
typedef Doubly_Link_List_Node* Node_Pointer;
typedef Doubly_Link_List_Node* Prev_Pointer;
typedef Doubly_Link_List_Node* Next_Pointer;
typedef Doubly_Link_List_Node* Node_Pool;
private:
static Node_Pool node_Pool;
public:
Value_Type value;
Prev_Pointer prev;
Next_Pointer next;
//有参构造
Doubly_Link_List_Node(Const_Value_Reference m_value,
Prev_Pointer m_prev,
Next_Pointer m_next)
:value(m_value), prev(m_prev), next(m_next)
{}
//默认构造
Doubly_Link_List_Node(Prev_Pointer m_prev = nullptr, Next_Pointer m_next = nullptr)
:prev(m_prev), next(m_next)
{}
//**************使用内存池技术改善效率************
//重载new和delete
void* operator new(size_t)
{
//内存池中没有申请到结点内存时,调用全局的new申请内存直接返回
if (node_Pool == nullptr)
return ::new Node;
//内存池中有结点时
Node_Pointer temp = node_Pool;
//从内存池中申请后,内存池中结点减少,即内存池首地址的指向下一个结点区域
node_Pool = node_Pool->next;
return temp;
}
void operator delete(void* free_node)
{
//释放结点内存直接将结点释放到内存池中
//每释放一个都插入到内存池的头部
//让释放的结点指向内存池首地址
((Node_Pointer)free_node)->next = node_Pool;
//让内存池的首地址指向释放的结点
node_Pool = (Node_Pointer)free_node;
}
};
template <typename T>
Doubly_Link_List_Node<T>* Doubly_Link_List_Node<T>::node_Pool = nullptr;
#endif
Doubly_Link_List.h
#pragma once
#include "Line_Table_ADT.h"
#include "Doubly_Link_List_Node.h"
#include<iostream>
#include<string>
template <typename T>
class Doubly_Link_List :public List<T>
{
public:
typedef Doubly_Link_List_Node<T> Node;
typedef Doubly_Link_List_Node<T>* Node_Pointer;
typedef Doubly_Link_List_Node<T>* Head_Pointer;
typedef Doubly_Link_List_Node<T>* Tail_Pointer;
typedef Doubly_Link_List_Node<T>* Current_Pointer;
typedef T Value_Type;
typedef const T& Const_Value_Reference;
private:
Head_Pointer head;
Tail_Pointer tail;
Current_Pointer curr;
int list_Length;
//初始化的函数,只用于此类,不提供对外接口
void init()
{
head = tail = curr = new Node;
list_Length = 0;
}
void removeAll()
{
while (head != nullptr)
{
curr = head;
head = head->next;
delete curr;
}
}
//满足某种异常条件,抛出异常,打印错误信息
void judge_OutOfRange(bool condition, const std::string& printInfo)
{
try
{
if (condition)
{
throw condition;
}
}
catch (bool)
{
std::cerr << printInfo << std::endl; //为什么不要在.h文件中使用using namespace std?
exit(1);
}
}
public:
Doubly_Link_List()
{
init();
}
~Doubly_Link_List()
{
removeAll();
}
void clear() override
{
removeAll();
init();
}
void insert(Const_Value_Reference value) override
{
Node_Pointer temp = new Node;
::new(temp)Node(value, curr,curr->next);
if (curr == tail)
tail = temp;
else
curr->next->prev = temp;
curr->next = temp;
list_Length++;
}
void append(Const_Value_Reference value) override
{
Node_Pointer temp = new Node;
::new(temp)Node(value, tail, tail->next);
tail->next = temp;
tail = temp;
list_Length++;
}
Value_Type remove() override
{
//判断链表是否为空
judge_OutOfRange(head->next == nullptr, "Link_List is none!");
Value_Type return_value = curr->next->value;
Node_Pointer temp = curr->next;
if (tail == curr->next)
tail = curr;
else
temp->next->prev = curr;
curr->next = temp->next;
delete temp;
list_Length--;
return return_value;
}
void prev() override
{
curr = curr->prev;
}
void next() override
{
curr = curr->next;
}
int length() const
{
return list_Length;
}
Const_Value_Reference getValue()
{
return curr->next->value;
}
int currPos()const override
{
Node* temp = head;
int i;
for (i = 0; temp != curr; i++)
{
temp = temp->next;
}
return i;
}
void moveToPosition(int position) override
{
judge_OutOfRange((position < 0 || position >= list_Length), "Position is out of range!");
curr = head;
for (int i = 0; i < position; i++)
curr = curr->next;
}
void print()
{
for (int i = 0; i < length(); i++)
{
moveToPosition(i);
std::cout << getValue() << std::endl;
}
}
};
main.cpp
#include <iostream>
#include "Doubly_Link_List.h"
using namespace std;
int main()
{
Doubly_Link_List<int> test_link_list;
cout << "测试insert和append函数" << endl;
test_link_list.insert(5);
test_link_list.insert(100);
test_link_list.insert(300);
test_link_list.append(400);
test_link_list.append(500);
test_link_list.print();
cout << "\n测试remove函数" << endl;
cout << "被删除的元素的值为:" << test_link_list.remove() << endl;
test_link_list.print();
cout << "\n测试prev、next、currPos" << endl;
cout << "当前指针位置为:" << test_link_list.currPos() << endl;
test_link_list.prev();
test_link_list.prev();
cout << "前移两次指针位置为:" << test_link_list.currPos() << endl;
test_link_list.next();
cout << "后移一次指针位置为:" << test_link_list.currPos() << endl;
cout << "\n测试length" << endl;
cout << "当前顺序表的长度为:" << test_link_list.length() << endl;
cout << "\n测试clear" << endl;
test_link_list.clear();
cout << "当前顺序表的长度为:" << test_link_list.length() << endl;
test_link_list.append(500);
cout << "当前顺序表的长度为:" << test_link_list.length() << endl;
test_link_list.print();
}
运行结果:
2.循环链表
循环链表的C++实现(有头指针和尾指针的单链表实现)
Single_Link_List_Node.h
#pragma once
#ifndef SINGLE_LINK_LIST_NODE
#define SINGLE_LINK_LIST_NODE
template <typename T>
class Single_Link_List_Node
{
public:
typedef T Value_Type;
typedef T* Value_Pointer;
typedef T& Value_Reference;
typedef const T& Const_Value_Reference;
typedef Single_Link_List_Node Node;
typedef Single_Link_List_Node* Node_Pointer;
typedef const Single_Link_List_Node& Const_Node_Reference;
typedef Single_Link_List_Node* Next_Pointer;
typedef Node* Node_Pool;
private:
static Node_Pool node_Pool; //声明为static变量,让所有对象共享
public:
Value_Type value; //结点存储的值
Next_Pointer next; //结点保存的指向下一个结点的指针
//结点构造函数,创建结点,对应C语言实现的create函数
Single_Link_List_Node(Const_Value_Reference m_value, Next_Pointer m_next = nullptr)
:value(m_value), next(m_next)
{
}
//默认构造函数
//为头指针,尾指针,当前指针的定义提供不用没有值的构造方法
Single_Link_List_Node(Next_Pointer m_next = nullptr)
{}
//重载new运算符
void* operator new(size_t)
{
//内存池中没有申请到结点内存时,调用全局的new申请内存直接返回
if (node_Pool == NULL)
return ::new Node;
//内存池中有结点时
Node_Pointer temp = node_Pool;
//从内存池中申请后,内存池中结点减少,即内存池首地址的指向下一个结点区域
node_Pool = node_Pool->next;
return temp;
}
//重载delete运算符
void operator delete(void* free_node)
{
//释放结点内存直接将结点释放到内存池中
//每释放一个都插入到内存池的头部
//让释放的结点指向内存池首地址
((Node_Pointer)free_node)->next = node_Pool;
//让内存池的首地址指向释放的结点
node_Pool = (Node_Pointer)free_node;
}
bool operator==(Const_Node_Reference node)
{
if (value == node.value && next == node.next)
return true;
}
};
//类的静态变量的初始化
template <typename T>
Single_Link_List_Node<T>* Single_Link_List_Node<T>::node_Pool = nullptr;
#endif
Circular_Linked.h
#pragma once
#ifndef CIRCULAR_LINKED_LIST_H
#define CIRCULAR_LINKED_LIST_H
#include "Single_Link_List_Node.h"
#include<iostream>
#include <string>
template<typename T>
class Circular_Linked_List
{
public:
typedef T Value_Type;
typedef const T& Const_Value_Reference;
typedef Single_Link_List_Node<T> Node;
typedef Single_Link_List_Node<T>* Node_Pointer;
typedef Single_Link_List_Node<T>* Head;
typedef Single_Link_List_Node<T>* Tail;
typedef Single_Link_List_Node<T>* Curr;
private:
Head head;
Tail tail;
Curr curr;
int size;
//初始化的函数,只用于此类,不提供对外接口
void init()
{
head = tail = curr = new Node;
size = 0;
}
void removeAll()
{
while (head->next !=head )
{
curr = head;
head = head->next;
tail->next = head;
delete curr;
}
delete head;
size = 0;
}
//满足某种异常条件,抛出异常,打印错误信息
void judge_OutOfRange(bool condition, const std::string& printInfo)
{
try
{
if (condition)
{
throw condition;
}
}
catch (bool)
{
std::cerr << printInfo << std::endl; //为什么不要在.h文件中使用using namespace std?
exit(1);
}
}
public:
//构造函数
Circular_Linked_List()
{
init();
}
//析构函数
~Circular_Linked_List()
{
removeAll();
}
void clear()
{
removeAll();
init();
}
//插入
void insert(Const_Value_Reference value)
{
if (head->next == nullptr)
{
tail = new Node; //使用operator new分配内存
::new(tail)Node(value, tail);
head->next = tail;
}
else
{
Node* temp = curr->next;
curr->next = new Node; //使用operator new分配内存
::new(curr->next)Node(value, temp);
if (curr == head)
{
tail->next = curr->next;
}
else if (curr == tail) //记得判断尾节点的特殊情况
{
tail = curr->next;
}
}
size++;
}
void append(Const_Value_Reference value)
{
if (head->next == nullptr)
{
tail = new Node; //使用operator new分配内存
::new(tail)Node(value, tail);
head->next = tail;
}
else
{
tail->next = new Node(value, tail->next);
tail = tail->next;
}
size++;
}
//移除
Value_Type remove()
{
//判断链表是否为空
judge_OutOfRange((head->next == nullptr), "Link_List is none!");
Value_Type remove_value = curr->next->value;
Node* temp = curr->next;
if (tail->next == tail)
{
head = curr = nullptr;
}
else if (tail->next != tail && curr == head)
{
curr->next = curr->next->next;
tail->next = curr->next;
}
else if (tail->next != tail && curr == tail)
{
curr->next = curr->next->next;
head->next= curr->next;
}
else
{
curr->next = curr->next->next;
}
delete temp;
size--;
return remove_value;
}
void prev()
{
if (curr == head)
return;
Node* temp = head;
while (temp->next != curr)
temp = temp->next;
curr = temp;
}
void next()
{
curr = curr->next;
}
int length() const
{
return size;
}
Const_Value_Reference getValue()
{
//判断链表是否为空
judge_OutOfRange((head->next == nullptr), "Link_List is none!");
return curr->next->value;
}
int currPos()const
{
Node* temp = head;
int i;
for (i = 0; temp != curr; i++)
{
temp = temp->next;
}
return i;
}
void moveToPosition(int position)
{
if(size!=0)
judge_OutOfRange((position < 0 || position >= size), "Position is out of range!");
curr = head;
for (int i = 0; i < position; i++)
curr = curr->next;
}
//遍历打印
void print()
{
for (int i = 0; i < length(); i++)
{
moveToPosition(i);
std::cout << getValue() << std::endl;
}
}
};
#endif
main.cpp
#include "pch.h"
#include <iostream>
#include "Circular_Linked_List.h"
using namespace std;
int main()
{
Circular_Linked_List<int> test_link_list;
cout << "测试insert和append函数" << endl;
test_link_list.insert(5);
test_link_list.insert(100);
test_link_list.insert(300);
test_link_list.append(400);
test_link_list.append(500);
test_link_list.print();
cout << "\n测试remove函数" << endl;
cout << "被删除的元素的值为:" << test_link_list.remove() << endl;
test_link_list.print();
cout << "\n测试prev、next、currPos" << endl;
cout << "当前指针位置为:" << test_link_list.currPos() << endl;
test_link_list.prev();
test_link_list.prev();
cout << "前移两次指针位置为:" << test_link_list.currPos() << endl;
test_link_list.next();
cout << "后移一次指针位置为:" << test_link_list.currPos() << endl;
cout << "\n测试length" << endl;
cout << "当前顺序表的长度为:" << test_link_list.length() << endl;
cout << "测试循环" << endl;
test_link_list.moveToPosition(0);
cout << test_link_list.getValue() << endl;
test_link_list.next();
cout << test_link_list.getValue() << endl;
test_link_list.next();
cout << test_link_list.getValue() << endl;
test_link_list.next();
cout << test_link_list.getValue() << endl;
test_link_list.next();
cout << test_link_list.getValue() << endl;
test_link_list.next();
cout << test_link_list.getValue() << endl;
test_link_list.next();
cout << test_link_list.getValue() << endl;
test_link_list.next();
cout << test_link_list.getValue() << endl;
test_link_list.next();
cout << test_link_list.getValue() << endl;
test_link_list.next();
cout << "\n测试clear" << endl;
test_link_list.clear();
cout << "当前顺序表的长度为:" << test_link_list.length() << endl;
test_link_list.append(500);
cout << "当前顺序表的长度为:" << test_link_list.length() << endl;
test_link_list.print();
}
运行结果: