剑指Offer___关于复杂链表的复制算法剖析
来源:互联网 发布:linux 70秒漏洞 编辑:程序博客网 时间:2024/06/05 01:51
本文的源代码和测试代码:https://github.com/clearoff/learngit/blob/master/ComplexLinklist.c
1、复杂链表的定义:
一般的,我们把只有一个数据于和一个指针的节点所组成的链表叫做单链表,由单链表我们引出了复杂链表的定义,如下图:
【复杂链表在C语言中的定义】:
typedef struct ComplexLinkNode{Datatype data;struct ComplexLinkNode *p_Next; //指向下一个节点的指针struct ComplexLinkNode *p_sibling; //指向任意一个节点或者空}ComplexLinkNode;
由图可知,复杂链表不光含有单链表中的指向下一个元素的指针,还含有一个指针可以指向任意一个节点或者NULL!
下来我们就来分析一下如何对这个复杂链表进行复制:
方法1:首先我们可以拷贝复杂链表中的单链表部分,并且让拷贝出来的链表所有节点的p_Sibling都指向NULL,
随后我们就要明确所拷贝链表中每一个p_Sibling指针的指向,我们可以先遍历源链表,用两个变量分别记录从头节点到p_Sibling指针不为NULL的节点和p_Sibling所指向节点的步数,然后从所拷贝的链表中找到相应的节点,并进行连接。
【相应C语言代码】:
ComplexLinkNode* Clone_Nodes(ComplexLinkNode* list) //时间复杂度为O(n*n)的方法{assert(list);ComplexLinkNode* list2 = NULL;ComplexLinkNode* cur1 = list;ComplexLinkNode* tmp = NULL;int count1 = 0; //记录原链表找到指针的步数int count2 = 0; //记录找到指针所指向节点的步数while (cur1) //先拷贝复杂链表中的单链表部分{ComplexLinkNode* New = NULL;New = (ComplexLinkNode*)malloc(sizeof(ComplexLinkNode)* 1); //开辟一个新节点if (New == NULL){printf("Out of memory!\n");exit(EXIT_FAILURE);}New->data = cur1->data;New->p_Next = NULL;New->p_sibling = NULL;if (list2 == NULL){list2 = New;tmp = list2;}else{tmp->p_Next = New;tmp = New;}cur1 = cur1->p_Next;}cur1 = list;while (cur1){ComplexLinkNode *pos1 = NULL;ComplexLinkNode *pos2 = NULL;count1 = 0;count2 = 0;if (cur1->p_sibling != NULL){ComplexLinkNode *pcur1 = list;ComplexLinkNode *pcur2 = list;pos1 = cur1;pos2 = cur1->p_sibling;while (pcur1 != pos1){count1++;pcur1 = pcur1->p_Next;}while (pcur2 != pos2){count2++;pcur2 = pcur2->p_Next;}pcur1 = list2;pcur2 = list2;while ((pcur1 != NULL)&&count1){count1--;pcur1 = pcur1->p_Next;}while ((pcur2 != NULL) && count2){count2--;pcur2 = pcur2->p_Next;}pcur1->p_sibling = pcur2;}cur1 = cur1->p_Next;}printf("复杂链表复制成功!\n");return list2;}由于这种算法需要两次遍历原链表,所以时间复杂度很高,为了减少时间复杂度,我们来参考一下第二种方法:
方法二:在克隆复杂链表中的单链表时,我们不重新建立头节点,而是直接把N节点的拷贝节点链在N节点的后面,
如下图:
【该步骤的C语言代码】:
ComplexLinkNode* CloneNodes(ComplexLinkNode *list) //复制复杂链表的pNext部分!{assert(list);ComplexLinkNode *pNode = list;while (pNode){ComplexLinkNode *pClone = (ComplexLinkNode*)malloc(sizeof(ComplexLinkNode)* 1);if (pClone == NULL){printf("Out of memory!\n");exit(EXIT_FAILURE);}pClone->data = pNode->data;pClone->p_Next = pNode->p_Next;pClone->p_sibling = NULL;pNode->p_Next = pClone;pNode = pClone->p_Next;}return list;}随后,我们在明确经过上面一个人步骤后链表中每一个节点的指向,找到了N节点p_Sibling指针不为NULL的节点后,我们只需要把N节点的下一个节点指向N节点p_Sibling所指向的节点的下一个节点就可以了。
【该步骤的C语言代码】:
ComplexLinkNode* ConnectSiblingNodes(ComplexLinkNode* head) //复制出来结点的p_sibling指针{assert(head);ComplexLinkNode* pNode = head;while (pNode){ComplexLinkNode* pClone = pNode->p_Next;if (pNode->p_sibling != NULL){pClone->p_sibling = pNode->p_sibling->p_Next;}pNode = pClone->p_Next;}return head;}
最后一步:切断原链表和拷贝出来的链表
【C语言代码】:
ComplexLinkNode* CutList(ComplexLinkNode* head){assert(head);ComplexLinkNode* head2 = NULL;ComplexLinkNode* pNode = head;ComplexLinkNode* pClone = NULL;if (pNode) //将克隆出来的节点连接头节点{head2 = pNode->p_Next;pClone = pNode->p_Next;pNode->p_Next = pClone->p_Next;pNode = pNode->p_Next;}while (pNode){pClone->p_Next = pNode->p_Next;pClone = pNode->p_Next;pNode->p_Next = pClone->p_Next;pNode = pNode->p_Next;}return head2;}
如果本文有问题,希望大家能提些意见!!!
1 0
- 剑指Offer___关于复杂链表的复制算法剖析
- 【数据结构】关于复杂链表的复制
- [算法学习]复杂链表的复制
- 算法题:复杂链表的复制
- 【剑指offer】复杂链表的复制
- 剑指Offer26复杂链表的复制
- 剑指offer--复杂链表的复制
- 剑指offer26:复杂链表的复制
- 《剑指offer》复杂链表的复制
- 剑指offer:复杂链表的复制
- 剑指offer - 复杂链表的复制
- 剑指Offer--复杂链表的复制
- 剑指offer:复杂链表的复制
- 【剑指offer】复杂链表的复制
- 剑指offer-复杂链表的复制
- 剑指offer:复杂链表的复制
- 剑指offer:复杂链表的复制
- [剑指offer]复杂链表的复制
- 2016年武汉大学计算机学院“新技术系列讲座”简介记录
- Android中的全局Context
- 切屏和控制按钮显示
- java找不到或无法加载主类
- 实现文件上传
- 剑指Offer___关于复杂链表的复制算法剖析
- NAT简介
- Masonry使用案例讲解
- 补第一次c++实验
- C++里的seekg(),tellg(),seekp(),tellp()函数
- 八皇后问题
- 【Android问题】解决 Android SDK下载和更新失败“Connection to https://dl-ssl.google.com refused”的问题
- "围观"设计模式(22)--行为型之职责链模式(Chain Of Responsibility Pattern)
- dpdk_ring剥离(单线程版)