C++程序 平铺链表

C++程序 平铺链表

简介

平铺链表(Flatten Linked List)是将嵌套的链表铺平成一个线性的链表的操作。形象地说,就是将一个多层级的链表变成只有一层级的链表。

例如,下面这个嵌套的链表:

1 -> 2 -> 3 -> 4 -> 5
         |         |
         6 -> 7    8 -> 9 -> 10
         |              |
         11             12 -> 13
                          |
                          14 -> 15 -> NULL

将变成如下的线性链表:

1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 13 -> 14 -> 15 -> NULL

本文将介绍如何通过C++程序来实现平铺链表的操作。

实现过程

定义数据结构

首先,我们需要定义链表节点的数据结构。由于链表是嵌套的,我们需要为链表节点增加一个子链表的指针。

struct ListNode {
    int val;
    ListNode *next;
    ListNode *child;
};

其中,val 表示节点的值;next 指向下一个相邻的节点;child 指向子链表的头节点。

递归实现

平铺链表可以通过递归实现。我们可以先将子链表铺平,然后将当前链表的尾节点与子链表的头节点相连。

class Solution {
public:
    ListNode* flatten(ListNode* head) {
        if (!head) {
            return nullptr;
        }

        ListNode *tail = head;
        while (tail->next) {
            tail = tail->next;
        }

        ListNode *cur = head;
        while (cur) {
            if (cur->child) {
                ListNode *next = cur->next;
                ListNode *child_tail = flatten(cur->child);
                cur->next = cur->child;
                cur->next->prev = cur;
                cur->child = nullptr;
                child_tail->next = next;
                if (next) {
                    next->prev = child_tail;
                }
                cur = tail;
            } else {
                cur = cur->next;
            }
        }

        return head;
    }
};

代码中涉及到一些指针的操作,下面将分别介绍它们的含义。

  • tail:定义一个指针,表示当前链表的尾节点。
  • next:记录当前节点的下一个相邻节点。
  • child_tail:定义一个指针,表示子链表的尾节点。

迭代实现

除了递归实现外,我们还可以通过迭代实现平铺链表。

class Solution {
public:
    ListNode* flatten(ListNode* head) {
        if (!head) {
            return nullptr;
        }

        ListNode *prev = nullptr;
        stack<ListNode *> stk;
        stk.push(head);

        while (!stk.empty()) {
            ListNode *cur = stk.top();
            stk.pop();

            if (prev) {
                prev->next = cur;
                cur->prev = prev;
            }
            prev = cur;

            if (cur->next) {
                stk.push(cur->next);
            }
            if (cur->child) {
                stk.push(cur->child);
                cur->child = nullptr;
            }
        }

        return head;
    }
};

代码中使用了一个栈,记录下一个要访问的节点。当栈为空时,说明所有节点已经访问完,即平铺链表完成。

示例代码

下面是一个完整的示例代码。

#include <iostream>
#include <stack>

using namespace std;

struct ListNode {
    int val;
    ListNode *next;
    ListNode *child;
};

class Solution {
public:
    ListNode* flatten(ListNode* head) {
        if (!head) {
            return nullptr;
        }

        ListNode *prev = nullptr;
        stack<ListNode *> stk;
        stk.push(head);

        while (!stk.empty()) {
            ListNode *cur = stk.top();
            stk.pop();

            if (prev) {
                prev->next = cur;
                cur->prev = prev;
            }
            prev = cur;

            if (cur->next) {
                stk.push(cur->next);
            }
            if (cur->child) {
                stk.push(cur->child);
                cur->child = nullptr;
            }
        }

        return head;
    }
};

void printList(ListNode *head) {
    while (head) {
        cout << head->val << " -> ";
        head = head->next;
    }
    cout << "NULL" << endl;
}

int main() {
    ListNode *head = new ListNode{1, nullptr, nullptr};
    head->next = new ListNode{2, nullptr, nullptr};
    head->next->next = new ListNode{3, nullptr, nullptr};
    head->next->next->next = new ListNode{4, nullptr, nullptr};
    head->next->next->next->next = new ListNode{5, nullptr, nullptr};
    head->next->child = new ListNode{6, nullptr, nullptr};
    head->next->child->next = new ListNode{7, nullptr, nullptr};
    head->next->next->next->child = new ListNode{8, nullptr, nullptr};
    head->next->next->next->child->next = new ListNode{9, nullptr, nullptr};
    head->next->next->next->child->next->next = new ListNode{10, nullptr, nullptr};
    head->next->child->child = new ListNode{11, nullptr, nullptr};
    head->next->next->next->child->next->child = new ListNode{12, nullptr, nullptr};
    head->next->next->next->child->next->child->next = new ListNode{13, nullptr, nullptr};
    head->next->next->next->child->next->child->next->child = new ListNode{14, nullptr, nullptr};
    head->next->next->next->child->next->child->next->child->next = new ListNode{15, nullptr, nullptr};

    Solution s;
    head = s.flatten(head);
    printList(head);

    return 0;
}

结论

通过本文的介绍,我们了解了如何通过C++程序来实现嵌套链表的平铺操作。主要分为递归和迭代两种实现方法。具体实现可参考本文提供的示例代码。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程