在一个多级双向链表中,节点除了有两个指针分别指向前后两个节点,还有一个指针指向它的子链表,并且子链表也是一个双向链表,它的节点也有指向子链表的指针,请将这样的多级双向链表展开成普通的双向链表

一个复杂的多级双向链表结构,我们需要将其展开成一个普通的双向链表。 下面使用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指针,以保持双向链表的特性。
  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值