经典面试题之复杂链表复制的简单实现

7 篇文章 0 订阅
2 篇文章 0 订阅

经典面试之复杂链表的简单实现

对于复杂链表复制问题,如果只是单纯的实现这个功能,他其实是不难的。你可以在时间空间没有要求的情况下勉强的实现它。(主要问题就在于Random指针的重新定位了)

我就简单说说那些个常规方法的繁琐实现了:

void ComplexListCopy(ComplexList &List, ComplexList &ListCopy);

1.借助于一个指针数组保存源链表的地址,然后在连接新链表之时重新遍历源链表,进行random的定位。大概的伪代码实现如下

void ComplexListCopy(ComplexList &List, ComplexList &ListCopy)
void ComplexListcopy(complexList &List,ComplexList &ListCop)
{
ComplexListNode* parr[100];
int Len = Length(List);///得到源链表长度
ComplexListNode *cur = List.head._next;//第一个
int i = 0;
//除了random,其他问题都没有;
while(cur)
{
parr[i++] = cur;
ComplexListNode *tmp = BuyNode(cur->_data);
PushBack(ListCop,tmp);
cur = cur->_next;
}

//通过遍历数组以及List确定ListCop的random连接问题
ComplexListNode *curC = ListCop.head._next;
i = 0;
while(curC)
{
ComplexListNode* tmp = List.head._next;//List 的头
int count = 0;
//找到random指向的下标数
while(tmp != parr[i])
{
tmp=tmp->_next;
}

tmp = ListCop.head._next;
while(count--)
{
curC->_randomPiont = tmp;
}
i++;
curC = curC->_next;
}
}

然而这个实在是太戳了,,浪费空间浪费时间。那么一种比较好的做法就是,不借助第三方变量,直接处在源链表中插入,然后通过相对位置处理了randomPoint 问题。这个图画的有些失败,简单说说

1上边的,,红色代表源链表,黄色为元链表中random的指向。你要做的就是,复制一个相同内容的节点插入它后边(途中黑色)

2根据相对位置处理链表中randomPoint的指向(下图中粉色的线条)
<span style="color: rgb(255, 0, 0);">			</span>黑色<span style="color:#ff0000;">->_randomPoint = 红色->_randomPoint->_next;</span>

void ComplexListCopy(ComplexList &List, ComplexList &ListCopy)
			cursi->_randomPoint = curdi->_randomPoint->_next;

3将红黑两个链表进行分离。


具体实现

数据类型的定义

<span style="color:#330099;">typedef int DataType;
typedef struct ComplexListNode
{
	DataType _data;
	struct ComplexListNode * _next;
	struct ComplexListNode * _randomPoint;
}ComplexListNode;</span>
<span style="color:#330099;">typedef struct ComplexList
{
<span style="white-space:pre">	</span>ComplexListNode head;
}ComplexList;
</span>
基本框架的搭建
void Init(ComplexList &List)
{
	List.head._data = 0;
	List.head._next = NULL;
	List.head._randomPoint = NULL;
}
void Destroy(ComplexList&List)
{
	ComplexListNode* cur = &List.head;
	while (cur)
	{
		ComplexListNode *tmp = cur;
		cur = cur->_next;
		free(tmp);
	}
}

ComplexListNode* BuyNode(DataType x)
{
	ComplexListNode* ret = (ComplexListNode*)malloc(sizeof(ComplexList));
	if (ret == NULL)
		return NULL;
	ret->_data = x;
	ret->_next = NULL;
	ret->_randomPoint = NULL;
	return ret;
}
ComplexListNode* FindNode(ComplexList &List, DataType x)
{
	ComplexListNode* cur = List.head._next;
	while (cur)
	{
		if (cur->_data == x)
			return cur;
		cur = cur->_next;
	}
	return NULL;
}
void PushFront(ComplexList &List, DataType x)
{
	ComplexListNode* tmp = BuyNode(x);
	tmp->_next = List.head._next;
	List.head._next = tmp;
}
//siPos源,diPos目标
void MakeComplex(ComplexList &List, DataType siData, DataType diData)
{
<span style="white-space:pre">	</span>ComplexListNode *siPos = FindNode(List, siData);
<span style="white-space:pre">	</span>ComplexListNode *diPos = FindNode(List, diData);
<span style="white-space:pre">	</span>if (siPos == NULL || diPos == NULL)
<span style="white-space:pre">		</span>return;
<span style="white-space:pre">	</span>siPos->_randomPoint = diPos;
}
void ShowComList(ComplexList &List)
{
	ComplexListNode* cur = List.head._next;
	printf("List    :");
	while (cur)
	{
		printf("%2d -->", cur->_data);
		cur = cur->_next;
	}
	printf("\nListComp:");
	cur = List.head._next;
	while (cur)
	{
		if (cur->_randomPoint)
			printf("%2d -->", cur->_randomPoint->_data);
		else
			printf("   -->");
		cur = cur->_next;
	}
	printf("\n");
}

核心函数实现
void ComplexListCopy(ComplexList &List, ComplexList &ListCopy)
{
	ComplexListNode *curdi = List.head._next;
	//BuyNode And  Insert in List;
	if (curdi == NULL)
		return;
<span style="white-space:pre">	</span>//实现插入
	while (curdi)
	{
		ComplexListNode *tmp = BuyNode(curdi->_data);
		tmp->_next = curdi->_next;
		curdi->_next = tmp;
		curdi = tmp->_next;
	}

	curdi = List.head._next;
	ComplexListNode *cursi = curdi->_next;
	ListCopy.head._next = cursi;
	//实现对_randomPoint 指针指向的处理
	while (curdi&&cursi)
	{
		if(curdi->_randomPoint!=NULL)
			cursi->_randomPoint = curdi->_randomPoint->_next;
		curdi = cursi->_next;
		if(curdi)
			cursi = curdi->_next;
	}
	curdi = &List.head;
	cursi = curdi->_next;
<span style="white-space:pre">	</span>//分开两条新旧两条链表
	while (cursi)
	{
		curdi->_next = cursi->_next;
		curdi = curdi->_next;
		cursi->_next = curdi->_next;
		cursi = cursi->_next;
	}
}
以下是输出实例

对于这个复杂链表的实现问题呢,其实重点还是思路问题,即使你有一定的语言基础,也不见得能想到这里。
所以没事的时间多多联系,开拓思路还是有好处的。

void ComplexListCopy(ComplexList &List, ComplexList &ListCopy)

			cursi->_randomPoint = curdi->_randomPoint->_next;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值