剑指Offer----面试题26:复杂链表的复制

题目:

请实现哈数ComplexListNode *Clone(ComplexListNode *pHead),复制一个复杂链表。在复杂链表中,每个结点除了有一个next指针指向下一个结点外,还有一个sibling指向链表的任意结点或者NULL。


分析:


如下图是一个含有5个结点的复杂链表,实箭头代表next指针,虚箭头代表sibling指针。指向NULL的指针没有画出。


第一步:根据原始链表的每个结点N创建对应的N‘,并把N’链接在N的后面。经过这一步,链表的形式如下图所示:


代码如下:
void CloneNode(ComplexListNode *pHead)
{
	ComplexListNode *node = pHead;
	
	while (node != NULL)
	{
		ComplexListNode *copy = new ComplexListNode();
		copy->element = node->element;
		copy->next = node->next;

		node->next = copy;
		node = copy->next;
	}
}

第二步:设置复制出来结点的sibling,假设原始链表上N的sibling指向结点S,那么其对应复制出来的N‘是N的next指向的结点,同样S’也是S的next指向的结点。经过这一步,链表的形式如下图所示:

代码如下:
void ConnectSibling(ComplexListNode *pHead)
{
	ComplexListNode *node = pHead;
	while (node != NULL)
	{
		ComplexListNode *copy = node->next;
		if (node->sibling != NULL)
			copy->sibling = node->sibling->next;
		else
			copy->sibling = NULL;
		node = copy->next;
	}
}

第三步:把这个长链表拆分成两个链表。把奇数位置的结点用next链接起来就是原始链表,把偶数为止的结点用next连接起来就是复制出来的链表。经过这一步,链表的形式如下图所示:

代码如下:
ComplexListNode *ReConnectNodes(ComplexListNode *pHead)
{
	ComplexListNode *node = pHead;
	ComplexListNode *copyHead = NULL;
	ComplexListNode *copyNode = NULL;

	if (node != NULL)
	{
		copyHead = copyNode = node->next;//复制链表的头结点
		node->next = copyNode->next;
		node = node->next;
	}

	while (node != NULL)
	{
		copyNode->next = node->next;
		copyNode = copyNode->next;
		node->next = copyHead->next;
		node = node->next;
	}

	return copyHead;
}

最后将上面上面三步合在一起即可:

ComplexListNode *Clone(ComplexListNode *pHead)
{
	CloneNode(pHead);
	ConnectSibling(pHead);
	return ReConnectNodes(pHead);
}

官方源代码(有改动):


头文件ComplexListNode.h
#ifndef COMPLEXLISTNODE_H
#define COMPLEXLISTNODE_H

namespace ComplexListNodeSpace
{
	struct ComplexListNode
	{
		int element;
		ComplexListNode *next;
		ComplexListNode *sibling;
	};

	ComplexListNode *CreateComplexListNode(int value);
	void ConnectComplexListNode(ComplexListNode *root, ComplexListNode *pNext, ComplexListNode *pSibling);
	void printComplexList(ComplexListNode *root);
	void DestoryComplexList(ComplexListNode *root);
}

#endif

复杂链表实现文件ComplexListNode.cpp
#include"ComplexListNode.h"
#include<iostream>

using std::cout;
using std::endl;

namespace ComplexListNodeSpace
{

	ComplexListNode *CreateComplexListNode(int value)
	{
		ComplexListNode *temp = new ComplexListNode();
		temp->element = value;
		temp->next = NULL;
		temp->sibling = NULL;

		return temp;
	}

	void ConnectComplexListNode(ComplexListNode *root, ComplexListNode *pNext, ComplexListNode *pSibling)
	{
		if (root == NULL)
			return;

		root->next = pNext;
		root->sibling = pSibling;
	}

	void printComplexList(ComplexListNode *root)
	{
		if (root == NULL)
		{
			cout << "The tree is empty" << endl;
			return;
		}

		ComplexListNode *temp = root;
		while (temp != NULL)
		{
			cout << "The value of this node is " << temp->element << endl;
			if (temp->sibling != NULL)
				cout << "The sibling value of this node is " << temp->sibling->element << endl;
			else
				cout << "The sibling of this node is NULL" << endl;

			temp = temp->next;
		}
	}

	void DestoryComplexList(ComplexListNode *root)
	{
		if (root == NULL)
			return;

		ComplexListNode *temp = root;
		while (temp != NULL)
		{
			root = root->next;
			delete temp;
			temp = root;
		}

		root = NULL;
	}
}

测试文件:
#include"ComplexListNode.h"
#include<cstdlib>
#include<cstdio>

using namespace ComplexListNodeSpace;

void CloneNodes(ComplexListNode* pHead);
void ConnectSiblingNodes(ComplexListNode* pHead);
ComplexListNode* ReconnectNodes(ComplexListNode* pHead);

ComplexListNode* Clone(ComplexListNode* pHead)
{
	CloneNodes(pHead);
	ConnectSiblingNodes(pHead);
	return ReconnectNodes(pHead);
}

void CloneNodes(ComplexListNode* pHead)
{
	ComplexListNode* pNode = pHead;
	while (pNode != NULL)
	{
		ComplexListNode* pCloned = new ComplexListNode();
		pCloned->element = pNode->element;
		pCloned->next = pNode->next;
		pCloned->sibling = NULL;

		pNode->next = pCloned;

		pNode = pCloned->next;
	}
}

void ConnectSiblingNodes(ComplexListNode* pHead)
{
	ComplexListNode* pNode = pHead;
	while (pNode != NULL)
	{
		ComplexListNode* pCloned = pNode->next;
		if (pNode->sibling != NULL)
		{
			pCloned->sibling = pNode->sibling->next;
		}

		pNode = pCloned->next;
	}
}

ComplexListNode* ReconnectNodes(ComplexListNode* pHead)
{
	ComplexListNode* pNode = pHead;
	ComplexListNode* pClonedHead = NULL;
	ComplexListNode* pClonedNode = NULL;

	if (pNode != NULL)
	{
		pClonedHead = pClonedNode = pNode->next;
		pNode->next = pClonedNode->next;
		pNode = pNode->next;
	}

	while (pNode != NULL)
	{
		pClonedNode->next = pNode->next;
		pClonedNode = pClonedNode->next;

		pNode->next = pClonedNode->next;
		pNode = pNode->next;
	}

	return pClonedHead;
}

// ====================测试代码====================
void Test(char* testName, ComplexListNode* pHead)
{
	if (testName != NULL)
		printf("%s begins:\n", testName);

	printf("The original list is:\n");
	printComplexList(pHead);

	ComplexListNode* pClonedHead = Clone(pHead);

	printf("======The cloned list is:\n");
	printComplexList(pClonedHead);
}

//          -----------------
//         \|/              |
//  1-------2-------3-------4-------5
//  |       |      /|\             /|\
//  --------+--------               |
//          -------------------------
void Test1()
{
	printf("\t==============test1:普通==============\n");
	ComplexListNode* pNode1 = CreateComplexListNode(1);
	ComplexListNode* pNode2 = CreateComplexListNode(2);
	ComplexListNode* pNode3 = CreateComplexListNode(3);
	ComplexListNode* pNode4 = CreateComplexListNode(4);
	ComplexListNode* pNode5 = CreateComplexListNode(5);

	ConnectComplexListNode(pNode1, pNode2, pNode3);
	ConnectComplexListNode(pNode2, pNode3, pNode5);
	ConnectComplexListNode(pNode3, pNode4, NULL);
	ConnectComplexListNode(pNode4, pNode5, pNode2);

	Test("Test1", pNode1);

	DestoryComplexList(pNode1);
}

// m_pSibling指向结点自身
//          -----------------
//         \|/              |
//  1-------2-------3-------4-------5
//         |       | /|\           /|\
//         |       | --             |
//         |------------------------|
void Test2()
{
	printf("\t==============test2:sibliing指向结点自身==============\n");
	ComplexListNode* pNode1 = CreateComplexListNode(1);
	ComplexListNode* pNode2 = CreateComplexListNode(2);
	ComplexListNode* pNode3 = CreateComplexListNode(3);
	ComplexListNode* pNode4 = CreateComplexListNode(4);
	ComplexListNode* pNode5 = CreateComplexListNode(5);

	ConnectComplexListNode(pNode1, pNode2, NULL);
	ConnectComplexListNode(pNode2, pNode3, pNode5);
	ConnectComplexListNode(pNode3, pNode4, pNode3);
	ConnectComplexListNode(pNode4, pNode5, pNode2);

	Test("Test2", pNode1);
	DestoryComplexList(pNode1);
}

// m_pSibling形成环
//          -----------------
//         \|/              |
//  1-------2-------3-------4-------5
//          |              /|\
//          |               |
//          |---------------|
void Test3()
{
	printf("\t==============test3:sibling形成环==============\n");
	ComplexListNode* pNode1 = CreateComplexListNode(1);
	ComplexListNode* pNode2 = CreateComplexListNode(2);
	ComplexListNode* pNode3 = CreateComplexListNode(3);
	ComplexListNode* pNode4 = CreateComplexListNode(4);
	ComplexListNode* pNode5 = CreateComplexListNode(5);

	ConnectComplexListNode(pNode1, pNode2, NULL);
	ConnectComplexListNode(pNode2, pNode3, pNode4);
	ConnectComplexListNode(pNode3, pNode4, NULL);
	ConnectComplexListNode(pNode4, pNode5, pNode2);

	Test("Test3", pNode1);
	DestoryComplexList(pNode1);
}

// 只有一个结点
void Test4()
{
	printf("\t==============test4:只有一个结点==============\n");
	ComplexListNode* pNode1 = CreateComplexListNode(1);
	ConnectComplexListNode(pNode1, NULL, pNode1);

	Test("Test4", pNode1);
	DestoryComplexList(pNode1);
}

// 鲁棒性测试
void Test5()
{
	printf("\t==============test5:空链表==============\n");
	Test("Test5", NULL);
}

int main()
{
	Test1();
	Test2();
	Test3();
	Test4();
	Test5();

	system("pause");
	return 0;
}

运行结果:
        ==============test1:普通==============
Test1 begins:
The original list is:
The value of this node is 1
The sibling value of this node is 3
The value of this node is 2
The sibling value of this node is 5
The value of this node is 3
The sibling of this node is NULL
The value of this node is 4
The sibling value of this node is 2
The value of this node is 5
The sibling of this node is NULL
======The cloned list is:
The value of this node is 1
The sibling value of this node is 3
The value of this node is 2
The sibling value of this node is 5
The value of this node is 3
The sibling of this node is NULL
The value of this node is 4
The sibling value of this node is 2
The value of this node is 5
The sibling of this node is NULL
        ==============test2:sibliing指向结点自身==============
Test2 begins:
The original list is:
The value of this node is 1
The sibling of this node is NULL
The value of this node is 2
The sibling value of this node is 5
The value of this node is 3
The sibling value of this node is 3
The value of this node is 4
The sibling value of this node is 2
The value of this node is 5
The sibling of this node is NULL
======The cloned list is:
The value of this node is 1
The sibling of this node is NULL
The value of this node is 2
The sibling value of this node is 5
The value of this node is 3
The sibling value of this node is 3
The value of this node is 4
The sibling value of this node is 2
The value of this node is 5
The sibling of this node is NULL
        ==============test3:sibling形成环==============
Test3 begins:
The original list is:
The value of this node is 1
The sibling of this node is NULL
The value of this node is 2
The sibling value of this node is 4
The value of this node is 3
The sibling of this node is NULL
The value of this node is 4
The sibling value of this node is 2
The value of this node is 5
The sibling of this node is NULL
======The cloned list is:
The value of this node is 1
The sibling of this node is NULL
The value of this node is 2
The sibling value of this node is 4
The value of this node is 3
The sibling of this node is NULL
The value of this node is 4
The sibling value of this node is 2
The value of this node is 5
The sibling of this node is NULL
        ==============test4:只有一个结点==============
Test4 begins:
The original list is:
The value of this node is 1
The sibling value of this node is 1
======The cloned list is:
The value of this node is 1
The sibling value of this node is 1
        ==============test5:空链表==============
Test5 begins:
The original list is:
The tree is empty
======The cloned list is:
The tree is empty
请按任意键继续. . .



普通链表的复制:

#include"List.h"
#include<iostream>


using std::cout;
using std::endl;

using  namespace ListSpace4;

ListNode *CopyList(ListNode *root)
{
	if (root == nullptr)
	{
		cout << "链表为空,无法复制" << endl;
		return nullptr;
	}

	ListNode *prev = nullptr;
	ListNode *node = nullptr;
	ListNode *head = nullptr;
	int count = 0;

	while (root != nullptr)
	{
		node = CreateListNode(root->element);
		++count;
		if (count == 1)
		{
			head = node;
		}
		else
		{
			prev->next = node;
		}
		prev = node;
		node->next = nullptr;
		root = root->next;
	}

	return head;
}

void test41()
{
	cout << "\t==========测试非空链表的复制==========" << endl;
	ListNode *list1 = CreateListNode(1);
	ListNode *list2 = CreateListNode(2);
	ListNode *list3 = CreateListNode(3);
	ListNode *list4 = CreateListNode(4);
	ListNode *list5 = CreateListNode(5);
	ListNode *list6 = CreateListNode(6);

	ConnectListNodes(list1, list2);
	ConnectListNodes(list2, list3);
	ConnectListNodes(list3, list4);
	ConnectListNodes(list4, list5);
	ConnectListNodes(list5, list6);
	ConnectListNodes(list6, NULL);

	cout << "复制链表之前:";
	printList(list1);
	cout << endl;
	cout << "复制链表之后:";
	ListNode *copy = CopyList(list1);
	printList(copy);
	cout << endl;
	DestoryList(&list1);
	DestoryList(&copy);
}

void test42()
{
	cout << "\t==========测试只有一个结点的链表==========" << endl;
	ListNode *list1 = CreateListNode(1);

	ConnectListNodes(list1, NULL);


	cout << "复制之前表之前:";
	printList(list1);
	cout << endl;
	cout << "反转链表之后:";
	ListNode *copy = CopyList(list1);
	printList(copy);
	cout << endl;
	DestoryList(&list1);
	DestoryList(&copy);

	DestoryList(&list1);

}

void test43()
{
	cout << "\t==========测试只有空链表==========" << endl;
	cout << "复制之前表之前:";
	printList(nullptr);
	cout << endl;
	cout << "反转链表之后:";
	ListNode *copy = CopyList(nullptr);
	printList(copy);
	cout << endl;
}

int main()
{
	test41();
	cout << endl;

	test42();
	cout << endl;

	test43();
	cout << endl;

	system("pause");
	return 0;
}

运行结果:
        ==========测试非空链表的复制==========
复制链表之前:1  2  3  4  5  6
复制链表之后:1  2  3  4  5  6

        ==========测试只有一个结点的链表==========
复制之前表之前:1
反转链表之后:1

        ==========测试只有空链表==========
复制之前表之前:The list is empty

反转链表之后:链表为空,无法复制
The list is empty


请按任意键继续. . .





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值