用C++实现一个基于模板的双向循环链表并且每个节点可以衍生出一条双向循环链表并加上详细的注释
时间: 2024-01-22 07:19:21 浏览: 88
下面是基于模板的双向循环链表的实现,每个节点可以衍生出一条双向循环链表,并加上详细的注释。
```c++
#include <iostream>
using namespace std;
// 定义双向循环链表节点
template<typename T>
struct ListNode{
T data; // 数据域
ListNode<T>* prev; // 前驱指针
ListNode<T>* next; // 后继指针
ListNode<T>* sublist; // 子列表指针
};
// 双向循环链表类
template<typename T>
class DoublyLinkedList{
private:
ListNode<T>* head; // 头指针
int length; // 链表长度
public:
// 构造函数
DoublyLinkedList(){
head = new ListNode<T>; // 创建一个头节点
head->prev = head; // 头节点的前驱指向自己
head->next = head; // 头节点的后继指向自己
head->sublist = nullptr; // 头节点的子列表指向空
length = 0; // 链表长度初始化为0
}
// 析构函数
~DoublyLinkedList(){
ListNode<T>* p = head;
ListNode<T>* q = nullptr;
while(p != nullptr){ // 循环删除每个节点
q = p->next;
delete p;
p = q;
}
head = nullptr;
length = 0;
}
// 获取链表长度
int getLength(){
return length;
}
// 在链表末尾添加一个节点
void addNode(T data){
ListNode<T>* p = head->prev; // 找到尾节点
ListNode<T>* q = new ListNode<T>; // 创建新节点
q->data = data; // 初始化新节点数据
q->prev = p; // 新节点的前驱指向尾节点
q->next = head; // 新节点的后继指向头节点
q->sublist = nullptr; // 新节点的子列表指向空
p->next = q; // 尾节点的后继指向新节点
head->prev = q; // 头节点的前驱指向新节点
length++; // 链表长度加1
}
// 删除链表中第一个值为data的节点
bool deleteNode(T data){
ListNode<T>* p = head->next; // 从头节点开始遍历
while(p != head){
if(p->data == data){ // 找到要删除的节点
p->prev->next = p->next; // 修改前驱节点的后继指向
p->next->prev = p->prev; // 修改后继节点的前驱指向
delete p; // 释放节点内存
length--; // 链表长度减1
return true;
}
p = p->next; // 继续向后遍历
}
return false; // 没有找到要删除的节点
}
// 在链表中查找第一个值为data的节点
ListNode<T>* findNode(T data){
ListNode<T>* p = head->next; // 从头节点开始遍历
while(p != head){
if(p->data == data){ // 找到要查找的节点
return p;
}
p = p->next; // 继续向后遍历
}
return nullptr; // 没有找到要查找的节点
}
// 在节点p处插入一个值为data的节点
bool insertNode(ListNode<T>* p, T data){
if(p == nullptr){ // 插入位置非法
return false;
}
ListNode<T>* q = new ListNode<T>; // 创建新节点
q->data = data; // 初始化新节点数据
q->prev = p->prev; // 新节点的前驱指向p的前驱
q->next = p; // 新节点的后继指向p
q->sublist = nullptr; // 新节点的子列表指向空
p->prev->next = q; // p的前驱节点的后继指向新节点
p->prev = q; // p的前驱指向新节点
length++; // 链表长度加1
return true;
}
// 衍生出一个新的双向循环链表
DoublyLinkedList<T>* derivative(ListNode<T>* p){
DoublyLinkedList<T>* sublist = new DoublyLinkedList<T>; // 创建新的双向循环链表
if(p != nullptr && p->sublist == nullptr){ // p节点存在且没有子列表
p->sublist = sublist->head; // 在p节点处记录子列表
return sublist; // 返回新的双向循环链表
}
return nullptr; // 衍生失败
}
// 打印链表中所有节点的数据
void printList(){
ListNode<T>* p = head->next; // 从头节点开始遍历
while(p != head){
cout << p->data << " ";
p = p->next; // 继续向后遍历
}
cout << endl;
}
// 打印节点p的子列表中所有节点的数据
void printSublist(ListNode<T>* p){
if(p != nullptr && p->sublist != nullptr){ // p节点存在且有子列表
DoublyLinkedList<T>* sublist = (DoublyLinkedList<T>*)(p->sublist); // 获取子列表的指针
sublist->printList(); // 打印子列表中所有节点的数据
}
}
};
int main(){
// 创建双向循环链表
DoublyLinkedList<int> list;
list.addNode(1);
list.addNode(2);
list.addNode(3);
list.addNode(4);
list.addNode(5);
// 打印链表中所有节点的数据
cout << "list: ";
list.printList();
// 在链表中查找第一个值为3的节点
ListNode<int>* p = list.findNode(3);
if(p != nullptr){
// 在节点p处插入一个值为6的节点
list.insertNode(p, 6);
// 打印链表中所有节点的数据
cout << "list after insert: ";
list.printList();
}
// 在节点p处衍生出一个新的双向循环链表
DoublyLinkedList<int>* sublist = list.derivative(p);
if(sublist != nullptr){
// 在子列表中添加节点
sublist->addNode(7);
sublist->addNode(8);
// 打印链表中所有节点的数据
cout << "list with sublist: ";
list.printList();
// 打印节点p的子列表中所有节点的数据
cout << "sublist of p: ";
list.printSublist(p);
}
// 删除链表中第一个值为4的节点
list.deleteNode(4);
// 打印链表中所有节点的数据
cout << "list after delete: ";
list.printList();
return 0;
}
```
注:上述代码中的衍生操作可以用指针实现,不需要使用额外的空间来记录子列表。
阅读全文