一个复杂的多级双向链表结构,我们需要将其展开成一个普通的双向链表。 下面使用cpp来解决这个问题,
#include <iostream>
// 定义多级双向链表的节点结构
class Node {
public:
int val;
Node* prev;
Node* next;
Node* child;
Node(int _val) : val(_val), prev(nullptr), next(nullptr), child(nullptr) {}
};
// 展开多级双向链表的函数
Node* flatten(Node* head) {
if (!head) return nullptr; // 如果头节点为空,直接返回
Node* current = head; // 当前处理的节点
while (current) {
if (current->child) { // 如果当前节点有子链表
Node* next = current->next; // 保存当前节点的下一个节点
Node* child = flatten(current->child); // 递归展开子链表
// 连接当前节点和子链表
current->next = child;
child->prev = current;
current->child = nullptr; // 清除child指针
// 找到子链表的最后一个节点
while (child->next) {
child = child->next;
}
// 连接子链表的最后一个节点和原来的next节点
child->next = next;
if (next) next->prev = child;
}
current = current->next; // 移动到下一个节点
}
return head; // 返回展开后的链表头节点
}
// 用于打印展开后的链表
void printList(Node* head) {
while (head) {
std::cout << head->val << " ";
head = head->next;
}
std::cout << std::endl;
}
// 主函数,用于测试
int main() {
// 创建一个多级双向链表
Node* head = new Node(1);
head->next = new Node(2);
head->next->prev = head;
head->next->next = new Node(3);
head->next->next->prev = head->next;
head->child = new Node(4);
head->child->next = new Node(5);
head->child->next->prev = head->child;
head->child->child = new Node(6);
head->child->child->next = new Node(7);
head->child->child->next->prev = head->child->child;
// 展开链表
Node* flattenedHead = flatten(head);
// 打印展开后的链表
std::cout << "Flattened list: ";
printList(flattenedHead);
return 0;
}
Node
类:定义了多级双向链表的节点结构,包含值、前向指针、后向指针和指向子链表的指针。flatten
函数:这是核心算法,它递归地展开多级链表。- 如果当前节点有子链表,我们先保存当前节点的下一个节点。
- 递归地展开子链表。
- 将展开的子链表插入到当前节点和其下一个节点之间。
- 清除当前节点的 child 指针。
- 继续处理下一个节点。
- 处理指针:在插入子链表时,我们需要小心地处理所有的指针,确保双向链表的完整性。
- 递归:使用递归可以优雅地处理多层嵌套的子链表。
上面的是递归的算法,
下面使用非递归的算法
#include <iostream>
#include <stack>
class Node {
public:
int val;
Node* prev;
Node* next;
Node* child;
Node(int _val) : val(_val), prev(nullptr), next(nullptr), child(nullptr) {}
};
Node* flatten(Node* head) {
if (!head) return nullptr;
Node* current = head;
std::stack<Node*> stack;
while (current) {
if (current->child) {
// 如果当前节点有下一个节点,将其推入栈中
if (current->next) {
stack.push(current->next);
}
// 连接当前节点和其子节点
current->next = current->child;
current->child->prev = current;
current->child = nullptr; // 清除child指针
}
// 如果到达链表末尾且栈不为空,连接到栈顶元素
else if (!current->next && !stack.empty()) {
current->next = stack.top();
stack.top()->prev = current;
stack.pop();
}
current = current->next;
}
return head;
}
// 用于打印展开后的链表
void printList(Node* head) {
while (head) {
std::cout << head->val << " ";
head = head->next;
}
std::cout << std::endl;
}
int main() {
// 创建一个多级双向链表
Node* head = new Node(1);
head->next = new Node(2);
head->next->prev = head;
head->next->next = new Node(3);
head->next->next->prev = head->next;
head->child = new Node(4);
head->child->next = new Node(5);
head->child->next->prev = head->child;
head->child->child = new Node(6);
head->child->child->next = new Node(7);
head->child->child->next->prev = head->child->child;
// 展开链表
Node* flattenedHead = flatten(head);
// 打印展开后的链表
std::cout << "Flattened list: ";
printList(flattenedHead);
return 0;
}
- 使用栈:我们使用一个栈来存储需要后续处理的节点。这替代了递归调用栈的作用。
- 迭代过程:
- 遍历链表,对每个节点进行处理。
- 如果当前节点有子节点:
- 如果当前节点还有下一个节点,将其压入栈中,以便后续处理。
- 将当前节点与其子节点相连,并清除child指针。
- 如果到达链表末尾且栈不为空:
- 将当前节点与栈顶元素(之前保存的next节点)相连。
- 弹出栈顶元素。
- 连接操作:在处理子链表和栈顶元素时,我们需要正确地设置prev和next指针,以保持双向链表的特性。