zoukankan      html  css  js  c++  java
  • C语言之复杂链表的复制(图示详解)

    什么是复杂链表?

    复杂链表指的是一个链表有若干个结点,每个结点有一个数据域用于存放数据,还有两个指针域,其中一个指向下一个节点,还有一个随机指向当前复杂链表中的任意一个节点或者是一个空结点。今天我们要实现的就是对这样一个复杂链表复制产生一个新的复杂链表。

    复杂链表的数据结构如下:

     1 typedef int DataType;        //数据域的类型
     2 
     3 //复杂链表的数据结构
     4 
     5 typedef struct ComplexNode
     6 
     7 {
     8 
     9 DataType _data ;                     // 数据
    10 
    11 struct ComplexNode * _next;          // 指向下个节点的指针
    12 
    13 struct ComplexNode * _random;        // 指向随机节点(可以是链表中的任意节点 or 空)
    14 
    15 }ComplexNode;

     

    上图就是一个复杂链表的例子,那么我们应该如何实现复杂链表的复制呢?

    1、首先我们应该根据已有的复杂链表创建一条新的复杂链表,但是这个新的复杂链表的所有的结点的random指针都指向空,这样是很好实现的,相当于我们创建了一条简单的单链表(newlist),我们要复制的链表不妨称之为oldlist。

     

     

    2、接下来我们应该把新创建的这条复杂链表(newlist)与已有的复杂链表(oldlist)合并成如下的形式:

     

     

    在这种情况下我们已经把两条复杂链表合并成了一条链表(称之为linklist),通过对这条链表(linklist)的观察,我们可以发现合并的链表(linklist)中属于newlist的结点pnew的上一个结点pold(属于oldlist的结点)的random指针所指向的结点的next指针就应该是pnew结点的randow指针所指向的结点。

    这样我们让pold和pnew指针一直往后走最后就可以实现对所有属于新创建的复杂链表(newlist)的random指针指向相应的结点的操作。构成的复杂链表如下图

     

     

    在完成以上的步骤之后我们所要做的工作就很简单了,我们只要把这一条链表linklist分开成我们的newlist链表和oldlist链表就可以了。

     

    这样我们就完美的完成了复杂链表的复制工作下面就是具体实现的代码:

     头文件complexnode.h:

     1 #ifndef __COMPLEX__NODE__H__
     2 
     3 #define __COMPLEX__NODE__H__
     4 
     5  
     6 
     7 //包含头文件
     8 
     9 #include <stdio.h>
    10 
    11 #include<stdlib.h>
    12 
    13 #include <assert.h>
    14 
    15  
    16 
    17  
    18 
    19 typedef int DataType;        //数据域的类型
    20 
    21  
    22 
    23 //复杂链表的数据结构
    24 
    25 typedef struct ComplexNode
    26 
    27 {
    28 
    29 DataType _data ;                                // 数据
    30 
    31 struct ComplexNode * _next;                // 指向下个节点的指针
    32 
    33 struct ComplexNode * _random;        // 指向随机节点(可以是链表中的任意节点 or 空)
    34 
    35 }ComplexNode;
    36 
    37  
    38 
    39 //创建一个复杂链表的结点
    40 
    41 ComplexNode * BuyComplexNode(DataType x);
    42 
    43  
    44 
    45 //打印复杂的单链表
    46 
    47 void Display(const ComplexNode * cplist);
    48 
    49  
    50 
    51 //复杂链表的复制
    52 
    53 ComplexNode * CopyComplexNode(ComplexNode * cplist);
    54 
    55  
    56 
    57 #endif//__COMPLEX__NODE__H__

    具体功能实现complexnode.c

      1 #include "complexnode.h"
      2 
      3  
      4 
      5 //创建一个复杂链表的结点
      6 
      7 ComplexNode * BuyComplexNode(DataType x)
      8 
      9 {
     10 
     11 ComplexNode *cnode = (ComplexNode *)malloc(sizeof(ComplexNode));
     12 
     13 if(cnode == NULL)//创建失败
     14 
     15 {
     16 
     17 perror("BuyComplexNode()::malloc");
     18 
     19 return NULL;
     20 
     21 }
     22 
     23 //创建成功
     24 
     25 cnode->_data = x;
     26 
     27 cnode->_next = NULL;
     28 
     29 cnode->_random = NULL;
     30 
     31 return cnode;
     32 
     33 }
     34 
     35  
     36 
     37 //打印复杂的单链表
     38 
     39 void Display(const ComplexNode * cplist)
     40 
     41 {
     42 
     43 ComplexNode *pnode = cplist;
     44 
     45 while (pnode)
     46 
     47 {
     48 
     49 printf("%d::%d -->",pnode->_data,pnode->_random->_data);
     50 
     51 pnode = pnode->_next;
     52 
     53 }
     54 
     55 printf("over
    ");
     56 
     57  
     58 
     59 }
     60 
     61  
     62 
     63 //复杂链表的复制
     64 
     65 ComplexNode * CopyComplexNode(ComplexNode * cplist)
     66 
     67 {
     68 
     69  
     70 
     71 ComplexNode * pold = NULL;
     72 
     73 ComplexNode * pnew = NULL;
     74 
     75 ComplexNode * newlist = NULL;//指向新的复杂链表的头结点的指针
     76 
     77 pold = cplist;
     78 
     79 //创建一条新的复杂链表
     80 
     81 while(pold != NULL)
     82 
     83 {
     84 
     85 ComplexNode * new_node = BuyComplexNode(pold->_data);
     86 
     87 if(newlist == NULL)//当新的复杂链表中没有结点时
     88 
     89 {
     90 
     91 newlist = new_node;
     92 
     93 }
     94 
     95 else//当新的复杂链表有结点时
     96 
     97 {
     98 
     99 ComplexNode * node = newlist;
    100 
    101 while(node->_next != NULL)//找到最后一个结点
    102 
    103 {
    104 
    105 node = node->_next;
    106 
    107 }
    108 
    109 node->_next = new_node;//插入新的结点
    110 
    111 }
    112 
    113 pold = pold->_next;
    114 
    115  
    116 
    117 }//创建新的复杂链表结束
    118 
    119  
    120 
    121 //合并两条复杂链表
    122 
    123 pold = cplist;
    124 
    125 pnew = newlist;
    126 
    127 while (pold)
    128 
    129 {
    130 
    131 ComplexNode * curold = NULL;
    132 
    133 ComplexNode * curnew = NULL;
    134 
    135 curold = pold->_next;
    136 
    137 curnew = pnew->_next;
    138 
    139 if(pold->_next == NULL)
    140 
    141 {
    142 
    143 pold->_next = pnew;
    144 
    145 pold = curold;
    146 
    147 pnew = curnew;
    148 
    149 break;
    150 
    151 }
    152 
    153 pold->_next = pnew;
    154 
    155 pnew->_next = curold;
    156 
    157 pold = curold;
    158 
    159 pnew = curnew;
    160 
    161 }//合并两条复杂链表结束
    162 
    163  
    164 
    165 //让新创建的那条复杂链表上的所有结点的random指针指向相应的结点
    166 
    167 pold = cplist;
    168 
    169 pnew = newlist;
    170 
    171 while (pnew)
    172 
    173 {
    174 
    175 pnew->_random = pold->_random->_next;
    176 
    177 pold = pnew->_next;
    178 
    179 if(pold == NULL)//这是pnew的_next指针已经指向空
    180 
    181 {
    182 
    183 break;
    184 
    185 }
    186 
    187 pnew = pold->_next;
    188 
    189 }//结束
    190 
    191  
    192 
    193 //分离合并后的复杂链表
    194 
    195 pold = cplist;
    196 
    197 pnew = newlist;
    198 
    199 while (pold)
    200 
    201 {
    202 
    203 ComplexNode * curold = NULL;
    204 
    205 ComplexNode * curnew = NULL;
    206 
    207 if(pnew->_next == NULL)//已经分离完成
    208 
    209 {
    210 
    211 pold->_next = NULL;
    212 
    213 pnew->_next = NULL;
    214 
    215 break;
    216 
    217  
    218 
    219 }
    220 
    221 curold = pold->_next->_next;
    222 
    223 curnew = pnew->_next->_next;
    224 
    225  
    226 
    227 pold->_next = curold;
    228 
    229 pnew->_next = curnew;
    230 
    231 pold = curold;
    232 
    233 pnew = curnew;
    234 
    235 }//分离合并的复杂链表结束
    236 
    237  
    238 
    239 return newlist;
    240 
    241 }

    测试代码test.c:

     1 #include "complexnode.h"
     2 
     3 //
     4 
     5 //复杂链表的复制。?个链表的每个节点,有?个指向next指针指向下?个节
     6 
     7 //点,还有?个random指针指向这个链表中的?个随机节点或者NULL,现在要
     8 
     9 //求实现复制这个链表,返回复制后的新链表。
    10 
    11 //ps: 复杂链表的结构
    12 
    13  
    14 
    15  
    16 
    17  
    18 
    19 void test()
    20 
    21 {
    22 
    23 ComplexNode * cplist;
    24 
    25 ComplexNode * copylist;
    26 
    27 ComplexNode * node1;
    28 
    29 ComplexNode * node2;
    30 
    31 ComplexNode * node3;
    32 
    33 ComplexNode * node4;
    34 
    35 cplist = BuyComplexNode(1);
    36 
    37 node1 = BuyComplexNode(2);
    38 
    39 node2 = BuyComplexNode(3);
    40 
    41 node3 = BuyComplexNode(4);
    42 
    43 node4 = BuyComplexNode(5);
    44 
    45 cplist->_next = node1;
    46 
    47 node1->_next = node2;
    48 
    49 node2->_next = node3;
    50 
    51 node3->_next = node4;
    52 
    53 cplist->_random = node3;
    54 
    55 node1->_random = node4;
    56 
    57 node2->_random = cplist;
    58 
    59 node3->_random = node1;
    60 
    61 node4->_random = node2;
    62 
    63 Display(cplist);
    64 
    65 copylist = CopyComplexNode(cplist);
    66 
    67 Display(copylist);
    68 
    69  
    70 
    71 }
    72 
    73 int main()
    74 
    75 {
    76 
    77 test();
    78 
    79 return 0;
    80 
    81 }

    程序的运行结果如下图:

     

     

  • 相关阅读:
    LeetCode 4 :Majority Element
    LeetCode 3 :Min Stack
    Oracle操作4
    plsql安装教程
    java Date与String互相转化
    Oracle操作3
    Oracle操作2
    Oracle操作
    Oracle11g修改密码
    Visual Studio2013完全卸载
  • 原文地址:https://www.cnblogs.com/kj1501120706/p/7113464.html
Copyright © 2011-2022 走看看