C++程序 将多级链表展开

C++程序 将多级链表展开

给定一个链表,每个节点除了指向下一个节点的指针外,还有一个child指针,它可能指向一个单独的链表。这些子列表可能有一个或多个自己的子节点,以此类推,产生一个多级数据结构,如下图所示。你被给出了列表第一层的头。将列表展开,以便所有节点都出现在单层链接列表中。您需要按以下方式展开列表:一级中的所有节点应首先出现,然后是第二级的节点,依此类推。

C++程序 将多级链表展开

上面的列表应转换为10->5->12->7->11->4->20->13->17->6->2->16->9->8->3->19->15

问题清楚地说明我们需要逐层展开。解决方案的想法是,我们从第一级开始,逐个处理所有节点,如果一个节点有一个子节点,那么我们将子节点附加在列表的末尾,否则,我们不做任何事情。处理完第一层后,所有下一级节点将附加在第一层之后。添加节点的过程也是同样的方式。
1) 取 “cur” 指针,它将指向列表的第一级的头
2) 取 “tail” 指针,它将指向第一层的末尾
3) 当 “curr” 不为 NULL 时,重复以下过程。
I) 如果当前节点有子节点,则
a) 将这个新的子列表附加到 “tail” 后面
tail->next = cur->child
b) 找到新子列表的最后一个节点并更新 “tail”
tmp = cur->child;
while (tmp->next != NULL)
tmp = tmp->next;
tail = tmp;
II) 移动到下一个节点,即 cur = cur->next

以下是上述算法的实现。

// C++程序,用于展开有next和child指针的列表
#include <bits/stdc++.h>
using namespace std;
  
// 宏,用于找到数组中的元素数量
#define SIZE(arr) (sizeof(arr) / 
                   sizeof(arr[0])) 
  
// 链表节点有数据,next指针和child指针
class Node 
{ 
    public:
    int data; 
    Node *next; 
    Node *child; 
}; 
  
// 创建一个带n个节点的链表的实用函数,节点的数据来自arr[],所有child指针都设置为NULL
Node *createList(int *arr, int n) 
{ 
    Node *head = NULL; 
    Node *p; 
  
    int i; 
    for (i = 0; i < n; ++i) 
    { 
        if (head == NULL) 
            head = p = new Node();
        else 
        { 
            p->next = new Node();
            p = p->next; 
        } 
        p->data = arr[i]; 
        p->next = p->child = NULL; 
    } 
    return head; 
} 
  
// 打印链表的所有节点的实用函数
void printList(Node *head) 
{ 
    while (head != NULL) 
    { 
        cout << head->data << " "; 
        head = head->next; 
    } 
    cout<<endl; 
} 
  
// 此函数创建输入列表。创建的列表与上图中所示相同
Node *createList(void) 
{ 
    int arr1[] = {10, 5, 12, 7, 11}; 
    int arr2[] = {4, 20, 13}; 
    int arr3[] = {17, 6}; 
    int arr4[] = {9, 8}; 
    int arr5[] = {19, 15}; 
    int arr6[] = {2}; 
    int arr7[] = {16}; 
    int arr8[] = {3}; 
  
    // 创建8个链接的列表
    Node *head1 = createList(arr1, 
                             SIZE(arr1)); 
    Node *head2 = createList(arr2, 
                             SIZE(arr2)); 
    Node *head3 = createList(arr3, 
                             SIZE(arr3)); 
    Node *head4 = createList(arr4, 
                             SIZE(arr4)); 
    Node *head5 = createList(arr5, 
                             SIZE(arr5)); 
    Node *head6 = createList(arr6, 
                             SIZE(arr6)); 
    Node *head7 = createList(arr7, 
                             SIZE(arr7)); 
    Node *head8 = createList(arr8, 
                             SIZE(arr8)); 
  
    /* 修改child指针以创建上面显示的列表 */
    head1->child = head2; 
    head1->next->next->next->child = head3; 
    head3->child = head4; 
    head4->child = head5; 
    head2->next->child = head6; 
    head2->next->next->child = head7; 
    head7->child = head8; 
  
  
    /* 返回第一个链接列表的头指针。请注意,head1可以访问所有节点 */
    return head1; 
} 
  
/* 展开多级链接列表的主要函数 */
void flattenList(Node *head) 
{ 
    // 基本情况
    if (head == NULL) 
    return; 
  
    Node *tmp; 
  
   /* 找到第一级链接列表的尾节点 */
    Node *tail = head; 
    while (tail->next != NULL) 
        tail = tail->next; 
  
    // 逐个遍历所有第一级链接列表的节点,直到到达尾节点
    Node *cur = head; 
    while (cur != tail) 
    { 
        // 如果当前节点有子节点
        if (cur->child) 
        { 
            // 将子节点附加到当前列表的末尾
            tail->next = cur->child; 
  
            // 更新尾节点到新的最后一个节点
            tmp = cur->child; 
            while (tmp->next) 
                tmp = tmp->next; 
            tail = tmp; 
        } 
  
        // 更改当前节点
        cur = cur->next; 
    } 
} 
  
// 主函数
int main(void) 
{ 
    Node *head = NULL; 
    head = createList(); 
    flattenList(head); 
    printList(head); 
    return 0; 
} 

输出:

10 5 12 7 11 4 20 13 17 6 2 16 9 8 3 19 15

时间复杂度: 由于每个节点最多被访问两次,因此时间复杂度为O(n),其中n是给定链表中节点的数量。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程

C++ 示例