c++数据结构链表和双头链表的实现
链表的基本概念不加以赘述,看看双头链表的定义如下:
在一个长度为L的链表List中,Input: head tail --->在List中查找head和tail值的链表的节点,从tail节点往后的链表连接到List的头部去,然后改变tail节点的next-->head,图如下:
下面看看c++版本的实现:
#ifndef LIST_H_
#define LIST_H_
#include<iostream>
#include<array>
#include<cassert>
template<typename T>
class List {
protected:
struct Node {
T data;
struct Node* parents;
struct Node* next;
Node(T d) :data(d) {
parents = nullptr;
next = nullptr;
}
Node() = default;
};
using node = struct Node;
using pnode = struct Node*;
void delete_list();
std::array<pnode, 2>A;//存储环路的两个节点
pnode intersection{ nullptr };//存储相交位置的节点
bool flag;//判断是否存在环路得标志位
bool flag2{ false };//判断是否转换为双头链表
void insert(pnode p);
public:
pnode phead;
//双头链表得头
pnode phead1;
pnode phead2;
List() = default;//default construct function
List(pnode p1) :phead(p1), phead1(nullptr), phead2(nullptr) {
phead = nullptr; phead->next = nullptr; phead->parents = nullptr;
phead1 = nullptr; phead1->next = nullptr; phead1->parents = nullptr;
phead2 = nullptr; phead2->next = nullptr; phead2->parents = nullptr;
A[0] = A[1] = nullptr;
}
List(T num);
List(List<T>& c);
List<T>& operator=(List<T>& c);
T& operator[](int index);
bool INTERSEC() const;//判断是否相交
std::size_t Len();//返回链表长度
//转换为单链表
void conver_to_list();
void insert(T n);
pnode find(T data);
std::size_t find_count(T c);//返回查找节点比较的次数
void print_list();
void convert_to_double(T m, T n);//转换为对应得双头链表
//找到环路节点
void find_loop() const;
bool empty();
~List() {
if (flag2 == true)
{
conver_to_list();
delete_list();
}
else if (flag2 == false)
{
delete_list();
}
}
};
template <typename T>
void List<T>::delete_list()
{
pnode p = nullptr;
if (phead != NULL)
{
while (phead)
{
p = phead->next;
delete phead;
phead = p;
}
}
}
template <typename T>
List<T>::List(T num)
{
phead = new node(num);
}
template <typename T>
List<T>::List(List<T>& c)
{
this->phead = c->phead;
}
template <typename T>
List<T>& List<T>::operator=(List<T>& c)
{
this->phead = c.phead;
return *this;
}
template <typename T>
T& List<T>::operator[](int index)
{
if (index < 0)
{
std::cout << "INDEX Error" << std::endl;
}
else
{
auto p2 = this->phead;
for (size_t i = 0; i < index; i++)
{
p2 = p2->next;
}
return p2->data;
}
}
template<typename T>
bool List<T>::INTERSEC() const
{
if (phead1 == nullptr && phead2 == nullptr)
{
throw "Please convert to a double-ended linked list first";
}
else {
if (intersection != nullptr)
{
std::cout << "存在相交的节点,相交的节点的值是:" << intersection->data << std::endl;
return true;
}
std::cout << "不相交" << std::endl;
}
return false;
}
template<typename T>
inline std::size_t List<T>::Len()
{
std::size_t size = 0;
pnode p1 = phead;
while (p1 != nullptr)
{
size++;
}
return size;
}
template<typename T>
void List<T>::conver_to_list()
{
if (phead1 != nullptr || phead2 != nullptr)
{
//对于输入的m==n在链表的首尾节点的时候的进行转换为原来的链表
if (phead1 != nullptr && phead2 == nullptr)
{
//没有环路m==n的时候
if (flag == false) {//在链表尾节点的时候
if (phead1 == phead)
{
phead1 = phead2 = nullptr;
}
//在链表头部的时候
else {
pnode pcur = phead1;
while (pcur->next != phead)
{
pcur = pcur->next;
}
pcur->next = nullptr;
phead->next = phead1;
phead->parents = nullptr;
phead1->parents = phead;
phead1 = phead2 = nullptr;
}
}
//存在环路
else if (flag == true)
{
assert(A[0] != A[1]);
//end在链表的末尾的时候
A[1]->next = nullptr;
phead1 = phead2 = nullptr;
}
}
else if (phead1 == nullptr && phead2 != nullptr)
{
assert(flag == true);
//first在头部end在中间的时候
pnode pcur = phead2;
while (true)
{
if (pcur->next == phead)
{
pcur->next = nullptr;
break;
}
pcur = pcur->next;
}
A[1]->next = nullptr;
A[1]->next = phead2;
phead2->parents = A[1];
phead1 = phead2 = nullptr;
}
//对于输入m==n但是在链表的中间位置的时候进行转化为原来的list
else if (phead1 != nullptr && phead2 != nullptr)
{
if (phead1 != phead2)
{
//处理m==n但是在链表中间的时候(注意:无环路)
if (flag == false)
{
//先找相同的节点然后把phead2的部分拉过去到后面即可
pnode pcur1 = phead1;
pnode pcur2 = phead2;
pnode pcur3 = nullptr;
while (true)
{
if (pcur1 == pcur2)
{
pcur2->next = nullptr;
pcur3 = pcur1;
break;
}
if (pcur1->next != nullptr)
{
pcur1 = pcur1->next;
}
else if (pcur2->next != nullptr)
{
pcur2 = pcur2->next;
}
}
pnode pcur4 = phead2;
while (pcur4->next != pcur3)
{
pcur4 = pcur4->next;
}
pcur4->next = nullptr;
pcur3->next = phead2;
phead2->parents = pcur3;
phead1 = phead2 = nullptr;
}
//处理不等于的时候的情形(这是一般的情况下):两个节点既不相等并且两个节点都不在头部或者末尾的地方
else
{
assert(A[0] != A[1]);
A[1]->next = nullptr;
//删除phead2的指向
pnode pcur1 = phead2;
while (true)
{
if (pcur1->next == intersection)
{
pcur1->next = nullptr;
break;
}
pcur1 = pcur1->next;
}
A[1]->next = phead2;
phead2->parents = A[1];
phead1 = phead2 = nullptr;
}
}
//first在头部 end在尾部的时候
else if (phead1 == phead2)
{
A[1]->next = nullptr;
phead->parents = nullptr;
phead1 = phead2 = nullptr;
}
}
flag2 = false;
}
assert(phead1 == nullptr && phead2 == nullptr);
}
template <typename T>
void List<T>::insert(T n)
{
//尾插法创建双向链表
if (phead == nullptr)
{
phead = new node(n);
}
else {
pnode pnew = new node(n);
//寻找插入位置
pnode pcur = phead;
while (pcur->next != nullptr)
{
pcur = pcur->next;
}
pcur->next = pnew;
pnew->parents = pcur;
}
}
template<typename T>
void List<T>::insert(pnode p)
{
if (phead == nullptr)
{
phead = p;
}
else {
pnode pnew = p;
//寻找插入位置
pnode pcur = phead;
while (pcur->next != nullptr)
{
pcur = pcur->next;
}
pcur->next = pnew;
pnew->parents = pcur;
}
}
template <typename T>
typename List<T>::pnode List<T>::find(T data)
{
pnode pcur = phead;
while (pcur != nullptr)
{
if (pcur->data == data)
{
return pcur;
}
pcur = pcur->next;
}
return nullptr;
}
template<typename T>
std::size_t List<T>::find_count(T c)
{
//确保phead并没有发生改变
pnode pcur = phead;
std::size_t count = 0;
while (pcur != nullptr)
{
count++;
if (pcur->data == c)
{
return count;
}
pcur = pcur->next;
}
return 0;
}
template <typename T>
void List<T>::print_list()
{
if (empty())
{
std::cout << "This is empty list" << std::endl;
}
else
{
pnode pcur = phead;
while (pcur != nullptr)
{
std::cout << "data:" << pcur->data << "\t";
if (pcur->next != nullptr)
{
std::cout << "next-data:" << pcur->next->data << "\t";
}
if (pcur->parents != nullptr)
{
std::cout << "parent-data" << pcur->parents->data << std::endl;
}
pcur = pcur->next;
}
}
}
template<typename T>
void List<T>::convert_to_double(T m, T n)
{
/*T m, n;
std::cout << "请输入m,n得值是多少:" << std::endl;
std::cin >> m >> n;*/
//查找对应得节点
pnode phead_m = find(m);
pnode phead_n = find(n);
if (phead_m == nullptr || phead_n == nullptr)
{
flag = false;//不存在环路
}
//如果查找到得是一样值
else if (phead_m == phead_n)
{
flag = false;//不存在环路但是可以创建双头链表
//case1 查找到得节点在list得头部节点上面
if (phead_m == phead)
{
pnode pcur = phead_m->next;
phead1 = pcur;
phead2 = nullptr;
pcur->parents = nullptr;
while (pcur->next != nullptr)
{
pcur = pcur->next;
}
pcur->next = phead_m;
phead_m->parents = pcur;
phead_m->next = nullptr;
}
//case2 查找到得两个节点都是list得尾部
else if (phead_m->next == nullptr)
{
phead1 = phead;
phead2 = nullptr;
}
//case3 查找得节点既不在链表得头部 也不再链表得尾部节点
else if (phead_m->next != nullptr && phead_m->parents != nullptr)
{
std::cout << "In middle with list" << std::endl;
pnode pcur = phead_m->next;
phead1 = phead;
pcur->parents = nullptr;
phead2 = pcur;
while (pcur->next != nullptr)
{
pcur = pcur->next;
}
pcur->next = phead_m;
//不修改父节点这个时候对于phead_m拥有两个父节点
phead_m->next = nullptr;
//相交
intersection = phead_m;
}
}
//如果查找的是两个完全不一样的值的时候
else if (phead_m != phead_n)
{
/*一个节点在头一个节点在尾部的时候
一个节点在尾部(头部),另一个节点在中间的时候
两个节点都在中间的时候
判断哪个节点在前哪个节点在后*/
//如果不等于必然存在环路
flag = true;
//case1判断前后关系并且进行调整
pnode first = new node, end = new node;
std::size_t c1 = find_count(m);
std::size_t c2 = find_count(n);
if (c1 > c2)
{
first = phead_n;
end = phead_m;
}
else if (c2 > c1)
{
first = phead_m;
end = phead_n;
}
//case2 一个节点在头部一个节点在尾部的时候(不相交)
//存放环路节点
A[0] = first;
A[1] = end;
std::cout << first->data << "\t" << end->data << std::endl;
if (first->parents == nullptr && end->next == nullptr)
{
first->parents = end;
end->next = first;
phead1 = phead2 = first;
}
//case3 first节点在头部,end节点在中间的时候,把end后面的拉过去 end->next=first即可(不相交)
else if (first->parents == nullptr && end->next != nullptr)
{
pnode pre = end->next;
phead1 = nullptr;//第一个头节点
end->next = first;//建立环路
pnode pre2 = pre;
while (pre->next != nullptr)
{
pre = pre->next;
}
pre->next = first;
pre2->parents = nullptr;
phead2 = pre2;
}
//case4 end在尾部 first在中间的时候(不相交)
else if (end->next == nullptr && (first->parents != nullptr && first->next != nullptr))
{
phead1 = phead;
end->next = first;
phead2 = nullptr;
}
//case5 first 和end 节点都在中间的时候(相交)
else if ((first->next != nullptr && first->parents != nullptr) && (end->next != nullptr && end->parents != nullptr))
{
phead1 = phead;
pnode pre = end->next;
pnode pre2 = pre;
pre2->parents = nullptr;
while (pre->next != nullptr)
{
pre = pre->next;
}
pre->next = first;
end->next = first;
first->parents = end;
phead2 = pre2;
intersection = first;
}
}
flag2 = true;
}
template<typename T>
void List<T>::find_loop() const
{
if (flag == false)
{
std::cout << "不存在环路" << std::endl;
}
else if (flag == true)
{
std::cout << "环路的首部是:" << A[0]->data << "\t"
<< "环路的尾部是:" << A[1]->data << std::endl;
}
}
template <typename T>
bool List<T>::empty()
{
if (phead == nullptr)
{
return true;
}
return false;
}
#endif