当前位置: 首页 > news >正文

复制含有随机指针节点的链表

【说明】:

  本文是左程云老师所著的《程序员面试代码指南》第二章中“复制含有随机指针节点的链表”这一题目的C++复现。

  本文只包含问题描述、C++代码的实现以及简单的思路,不包含解析说明,具体的问题解析请参考原书。

  感谢左程云老师的支持。

【题目】:

  一种特殊的链表节点类描述如下:

1 struct Node
2  12 {
3  13     int value;
4  14     Node *next;
5  15     Node *rand;
6  16 };
View Code

  Node 中的 value 是节点值,next 指针和正常链表中的 next 指针的意义一样,都指向下一个节点,rand 指针是 Node 类中新增的指针,这个指针可能指向链表中的任意一个节点,也可能指向 NULL。

  给定一个由 Node 节点类型组成的无环单链表的头节点 head,请实现一个函数完成这个链表中所有结构的复制,并返回复制的新链表的头节点。例如:链表1->2->3->NULL。假设 1 的 rand 指针指向 3,2 的 rand 指针指向NULL,3 的 rand 指针指向 1。复制后的链表应该也是这种结构,比如, 1‘-2'->3'->NULL,1' 的 rand 指针指向 3,2' 的 rand 指针指向 NULL,3' 的 rand 指针指向 1‘,最后返回 1‘。

【进阶】:

  不是用额外的数据结构,只使用有限几个变量,且在时间复杂度为 O(N)内完成原问题要实现的函数。

【思路】:

  普通解法:使用hash_map

  进阶解法:1->2->3-NULL   ------>    1->1'->2->2'->3->3'->NULL

  不管是普通算法还是进阶算法找到 rand 所对应的 Node 是关键。

【编译环境】:

  CentOS6.7(x86_64)

  gcc 4.4.7

 【实现】:

  实现及测试代码:

  1 /*
  2  *文件名:listWithRand_copy.cpp
  3  *作者:
  4  *摘要:复制含有随机指针节点的链表
  5  */
  6 
  7 #include <iostream>
  8 #include <hash_map>
  9 
 10 using namespace std;
 11 using namespace __gnu_cxx;
 12 
 13 struct Node
 14 {
 15     int value;
 16     Node *next;
 17     Node *rand;
 18 };
 19 
 20 //使用hash_map所需要的hash函数
 21 struct hash_Node
 22 {
 23     size_t operator() (const Node &node) const
 24     {
 25         return node.value;
 26     }
 27 };
 28 
 29 //使用hash_map所需要的比较函数
 30 struct compare_Node
 31 {
 32     bool operator() (const Node &n1,const Node &n2) const
 33     {
 34         return n1.value == n2.value && n1.next == n2.next && n1.rand == n2.rand;
 35     }
 36 };
 37 
 38 //使用hash_map解决问题
 39 Node* copyListWithRand1(Node *head)
 40 {
 41     hash_map<Node,Node,hash_Node,compare_Node> map;
 42     Node *cur = head;
 43     while(NULL != cur)
 44     {
 45         Node *ptr = new Node;
 46         ptr->value = cur->value;
 47         ptr->next = NULL;
 48         ptr->rand = NULL;
 49         map[*cur] = *ptr;    //一一对应的关系
 50         cur = cur->next;
 51     }
 52     cur = head;
 53     while(NULL != cur)
 54     {
 55         map[*cur].next = cur->next;
 56         map[*cur].rand = cur->rand;
 57         cur = cur->next;
 58     }
 59     return &map[*head];
 60 }
 61 
 62 Node* copyListWithRand2(Node *head)
 63 {
 64     if(NULL == head)
 65         return NULL;
 66     Node *cur = head;
 67     Node *next = NULL;
 68     while(NULL != cur)
 69     {
 70         next = new Node;
 71         next->value = cur->value;
 72         next->next = cur->next;
 73         next->rand = NULL;
 74         cur->next = next;
 75         cur = next->next;
 76     }
 77     
 78     cur = head;
 79     Node *curCopy = NULL;
 80     while(NULL != cur)    //复制rand
 81     {
 82         next = cur->next->next;
 83         curCopy = cur->next;
 84         curCopy->rand = NULL != cur->rand ? cur->rand->next : NULL;
 85         cur = next;
 86     }
 87     
 88     Node *res = head->next;
 89     cur = head;
 90     while(NULL != cur)
 91     {
 92         next = cur->next->next;
 93         curCopy = cur->next;
 94         cur->next = next;
 95         curCopy->next = NULL != next ? next->next : NULL;
 96         cur = next;
 97     }
 98     return res;
 99 }
100 
101 void printListWithRand(Node *head)
102 {
103     while(NULL != head)
104     {
105         if(NULL != head->rand)
106             cout << head->value << " rand is: " << head->rand->value << endl;
107         else
108             cout << head->value << " rand is: NULL " << endl;
109             
110         if(NULL != head->next)
111             cout << head->value << " next is: " << head->next->value << endl;
112         else
113             cout << head->value << " next is: NULL " << endl;
114         head = head->next;
115     }
116 }
117 
118 int main()
119 {
120     Node *head = NULL;
121     Node *ptr = NULL;
122     
123     for(int i =0;i<4;i++)//构造链表
124     {
125         if(NULL == head)
126         {    
127             head = new Node;
128             head->value = i;
129             head->next = NULL;
130             head->rand = NULL;
131             ptr = head;
132             continue;
133         }
134         ptr->next = new Node;
135         ptr->rand = ptr->next;
136         ptr = ptr->next;
137         ptr->value = i;
138         ptr->next = NULL;
139         ptr->rand = NULL;
140     }
141     
142     cout << "before copy:" << endl;
143     printListWithRand(head);    
144 
145     cout << "Using hash_map to copy:" << endl;
146     ptr = copyListWithRand1(head);
147     printListWithRand(ptr);    
148 
149     cout << "Using advanced algorithm to copy:" << endl;
150     ptr = copyListWithRand2(head);
151     printListWithRand(ptr);    
152     return 0;
153 }
View Code

【说明】

  关于hash_map的使用,依然请参考[Z]C++ STL中哈希表 hash_map介绍

  使用 struct 来声明节点貌似不太符合C++哈,下次开始使用 class 来声明

 

注:

  转载请注明出处;

  转载请注明源思路来自于左程云老师的《程序员代码面试指南》。

转载于:https://www.cnblogs.com/PrimeLife/p/5374358.html

相关文章:

  • Android 文件式数据库Realm
  • mobAndroid免费验证短信
  • 【css3】浏览器内核及其兼容性
  • 一个苹果开发者的苹果表体验报告
  • 责任链模式
  • C 数据结构与算法系列 插入排序
  • spring-001-Ioc 顶层容器
  • Android自动化测试之Monkeyrunner使用方法及实例
  • 【案例】slave_net_timeout 问题一则
  • Node+Express+node-mysql 实战于演习 全套mysql(增删改查)
  • 我与mongodb 二三事(2)
  • 失眠的症状是什么
  • 20145222黄亚奇《Java程序设计》实验二实验报告
  • TaskCompletionSource的使用场景
  • Nginx负载均衡配置实例详解(转)
  • 【译】React性能工程(下) -- 深入研究React性能调试
  • Apache Pulsar 2.1 重磅发布
  • JS笔记四:作用域、变量(函数)提升
  • LeetCode刷题——29. Divide Two Integers(Part 1靠自己)
  • Linux gpio口使用方法
  • react-core-image-upload 一款轻量级图片上传裁剪插件
  • uva 10370 Above Average
  • vue脚手架vue-cli
  • Yii源码解读-服务定位器(Service Locator)
  • 构建二叉树进行数值数组的去重及优化
  • 诡异!React stopPropagation失灵
  • 机器学习 vs. 深度学习
  • 记录:CentOS7.2配置LNMP环境记录
  • 实现菜单下拉伸展折叠效果demo
  • 使用 @font-face
  • 使用 5W1H 写出高可读的 Git Commit Message
  • 线上 python http server profile 实践
  • 国内开源镜像站点
  • ​2020 年大前端技术趋势解读
  • #if 1...#endif
  • $ git push -u origin master 推送到远程库出错
  • ( )的作用是将计算机中的信息传送给用户,计算机应用基础 吉大15春学期《计算机应用基础》在线作业二及答案...
  • (附源码)apringboot计算机专业大学生就业指南 毕业设计061355
  • (四)linux文件内容查看
  • (轉貼) 2008 Altera 亞洲創新大賽 台灣學生成果傲視全球 [照片花絮] (SOC) (News)
  • .NET 8.0 发布到 IIS
  • .NET设计模式(7):创建型模式专题总结(Creational Pattern)
  • ::
  • @Transaction注解失效的几种场景(附有示例代码)
  • [ C++ ] STL---string类的模拟实现
  • [AutoSar]工程中的cpuload陷阱(三)测试
  • [BJDCTF2020]The mystery of ip1
  • [BZOJ] 2427: [HAOI2010]软件安装
  • [C#]使用PaddleInference图片旋转四种角度检测
  • [C#基础知识]专题十三:全面解析对象集合初始化器、匿名类型和隐式类型
  • [CF703D]Mishka and Interesting sum/[BZOJ5476]位运算
  • [ISCTF 2023]——Web、Misc较全详细Writeup、Re、Crypto部分Writeup
  • [Java算法分析与设计]--线性结构与顺序表(List)的实现应用
  • [LeetCode] Contains Duplicate
  • [LeetCode]剑指 Offer 40. 最小的k个数