`

复制特殊链表

 
阅读更多

转自<http://blog.sina.com.cn/s/blog_69824c1f0100v4ob.html>

struct node
        {
             int data;
             struct node * next;
             struct node * random;
        };

        本题来源是ms的一道面试题,要求是将一条有特殊结构的链表进行复制,链表的结构如上,除了正常的2个域之外,多了一个random,它代表一个指向链表 上某一任意节点的指针,要求将该链表复制。如图,其中实线表示next域,虚线表示random域。

拷贝特殊链表,有随机指针 - 飞云 - 我是飞云


        难点分析:本题最难的部分就在于如何将random域完好无损的完全拷贝复制到新的链表之上,对于普通链表一个while循环拷贝就可以搞定,但是这里似乎不可行。

        突破点:如何保存或记录random域可以作为一个思考的参考点,下面提供2种解法:
        1. hash缓存: 我们可以定义一个hash表,key为被拷贝链表中Node的地址,value为新的拷贝链表中Node的值。下面将在伪代码中进一步说明

        伪代码如下:
        struct node * old_list;
        struct node * new_list;

        hash ht;
        while( old_list != NULL )
        {
            if( ht.get(old_list) == NULL )   
        // 当前节点没有被复制过,则拷贝节点,同时将原节点的地址作为key,插入hash表
            {
            new_node = copy(*old_list);
            ht.set(old_list, new_node);
        }
        else    // 已经存在则直接将该节点读出
        {
            new_node = ht.get(old_list);
        }
          // 并将新复制的节点插入链表
          insert(new_list, new_node);
   
          if( ht.get(old_list->random) == NULL )   
          // 如果ht的random不存在,那么产生一个random node,并放入hash表
          {
                random_node = copy(*(old_list->random));
                ht.set(old_list->ramdon,random_node);
        }
            else    //否则从hash表中读出random
          {
              random_node = ht.get(old_list->random);
            }
            // 将random域进行填充
            new_node->random = random_node;
        }

        这样可以看出,因为地址值是唯一存在的,所以Hash函数的设计可以保证每个节点的值都会被一一映射,并且由于每一个节点都只会被复制一次,并且在代码的遍历过程中就已经完全复制好,空间复杂度为O(n),时间复杂度为O(n)

        2. 用一个图的方法看的比较清楚,首先在遍历原来链表的过程中,插入新的节点,比如A_N是copy(A_O)的,同时将A_N->next = A_O->next; A_O->next = A_N;通过一个遍历,我们就可以将链表复制成图中的样子。在完成next域的链接后,需要开始做random域的复制。

拷贝特殊链表,有随机指针 - 飞云 - 我是飞云


        在实现了next的结构之后,我们需要开始对new_list的random域和next域进行赋值。
        那么有: A_N->random = A_O->random->next;
        入图所示:A_O->random为C_O,C_O的next为C_N,这样A_N->random = C_N;
        对于 A_N->next = A_N->next->next;即B_N;
        该算法复杂度为O(N),空间复杂度为O(1),除了新拷贝的空间之外没有额外地址;

分享到:
评论

相关推荐

    复杂链表的复制1

    此外,对于空链表的情况,如代码中所示,需要特殊处理,确保函数能够正确返回 NULL。 总的来说,复杂链表的复制是一个涉及到链表操作和指针处理的复杂问题,通过巧妙地在原始链表上构建副本并逐步调整指针关系,...

    拷贝具有随机指针节点的链表,

    在本问题中,我们关注的是一个特殊的链表,其中包含了一个额外的随机指针(random pointer),这个指针可以指向链表中的任意节点,而不仅限于下一个节点。这个数据结构在某些算法问题和复杂数据模型中非常有用。 ...

    循环链表(八种功能)

    循环链表是一种特殊的线性表,它通过将链表的尾节点指向头节点,形成了一个闭环的数据结构。与普通链表相比,循环链表在处理某些问题时更加方便,比如实现队列、模拟游戏中的轮流机制等。 ### 八种功能概述 1. **...

    C完整链表C完整链表C完整链表

    本例中的代码虽然存在一些不易理解的部分(如注释中的特殊字符),但整体上展示了如何在C语言中创建和操作链表。 以上就是对提供的文件信息进行的详细分析和解释,希望这些知识点能够帮助您更深入地了解C语言中的...

    循环链表实验报告(word文档,详细解说)

    循环链表是一种特殊的链式数据结构,其特点是最后一个节点的指针指向列表的开头,形成一个闭合的循环。在本实验报告中,学生需要实现循环链表的相关操作,包括插入、复制、查找、判断空表以及删除等功能,并对这些...

    c语言双链表实现

    DOUBLE链表是一种特殊的链表,它具有双向链表的特点,即每个节点都有两个指针,一个指向上一个节点,另一个指向下一个节点。今天,我们将讲述如何使用c语言实现DOUBLE链表。 首先,我们需要定义DOUBLE链表的结构体...

    关于链表的一些面试题

    对于检测两个链表是否有交点的问题,首先需要考虑特殊情况,即两个链表的头指针相同,那么它们自然有交点。对于一般情况,可以通过比较两个链表的长度来解决。计算两个链表的长度len1和len2,然后让指针p1从较长链表...

    C语言数组形链表实现

    在C语言中,数组形链表是一种特殊的数据结构,它结合了数组的高效访问和链表的灵活扩展性。这种数据结构通常用于处理动态数组,其中元素可以方便地添加或删除,而不需要像传统数组那样预先知道确切的大小。本文将...

    剑指offer~复杂链表的复制(Java)

    输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会...

    静态链表的C语言实现

    但由于静态链表的特殊性,指针域不再是实际的内存地址,而是数组中的下标。 ```c typedef struct Node { int data; // 数据域 int next_index; // 指针域,表示下一个节点在数组中的下标 } StaticListNode; ``` ...

    链表的各种操作

    链表复制涉及创建一个新的链表,其中每个节点都对应原链表的一个节点。这需要为每个原链表的节点创建新的节点,并设置相应的数据和指针。 8. 链表的排序: 链表可以使用各种排序算法进行排序,如冒泡排序、选择排序...

    C语言之复杂链表的复制方法(图示详解)

    复杂链表是一种特殊的链表结构,它的每个结点不仅有一个指向下一个节点的指针,还有一个随机指针域,该指针域可以指向链表中的任意一个节点或为空结点。这种链表结构使得链表的操作变得更加复杂。 二、复杂链表的...

    数据结构中十字链表的C语言实现

    十字链表是一种特殊的链表形式,它主要用于稀疏矩阵的存储。在稀疏矩阵中,非零元素的数量远少于零元素的数量,因此采用普通的二维数组存储会浪费大量空间。十字链表通过存储非零元素的位置和值来高效地表示这种矩阵...

    数据结构试验1-链表和顺序表

    6. **动态数组扩容**:当顺序表满时,创建新数组并复制旧数组元素,然后释放旧数组。 7. **性能比较**:通过实验比较链表和顺序表在不同操作下的性能差异,如插入、删除和查找。 这个实验将帮助你深入理解这两种...

    队列的链表与数组分别实现

    队列是一种特殊的线性数据结构,它遵循“先进先出”(FIFO,First In First Out)的原则。在计算机科学中,队列被广泛应用在任务调度、数据缓冲、多线程同步等多个领域。本篇文章将深入探讨如何用数组和链表两种数据...

    C++设计异秩链表实现学校人员的信息管理vs2008

    在C++编程中,"异秩链表"是一种特殊的链表结构,它的每个节点可以包含不同类型的附加数据,这在处理具有多种不同类型元素的数据集合时非常有用。在本例中,设计了一个用C++实现的异秩链表,用于管理学校人员的信息,...

    单向链表操作详解(二)

    “单向链表操作详解(二)”这篇文档可能还涵盖了特殊情况的处理,例如空链表操作、错误处理以及优化链表操作的技巧等。通过详尽的实例和解释,读者可以深入理解单链表的工作原理,并学会在实际编程中灵活运用。阅读...

    C语言之复杂链表的复制详解

    在C语言中,复杂链表是一种特殊的链表结构,每个节点不仅包含数据域和指向下一个节点的指针,还包含一个额外的指针域,该指针可以指向链表中的任意节点或为空。这种结构使得复杂链表的操作相比简单链表更加复杂,但...

    lianbiao.rar_数据结构作业_链表题

    9. **链表的复制**:创建链表的一个完全副本,这需要深拷贝所有节点。 在www.pudn.com.txt文件中,可能包含了题目说明、样例输入输出或者其他相关资料,帮助理解作业要求和测试用例。 总的来说,这个作业涵盖了...

    多项式相加链表求解

    - 如果第一个多项式的指数大于第二个,则将第二个多项式的当前节点复制到结果链表中。 - 如果第一个多项式的指数小于第二个,则将第一个多项式的当前节点复制到结果链表中。 - 最后处理剩余的节点。 #### 主函数 ``...

Global site tag (gtag.js) - Google Analytics