题目:
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),实现链表的复制。
分析:
首先想到的是先将链表的下一个节点链路复制出一条链表,再从头开始将链表的任意节点指针复制,问题在于任意节点的指针可以指向任意位置,每个节点都要从头查找。
由于链表的顺序性,可以将复制链表复制在原链表内部,最后拆分为两个单独的复杂链表即可。这样任意节点的指针就可以根据原链表节点之间找到,无需遍历查找。
实现:
<span style="font-family:Microsoft YaHei;font-size:14px;">public RandomListNode Clone(RandomListNode pHead) {
if (pHead == null) {
return null;
}
clone(pHead);
random(pHead);
return copylist(pHead);
}
public void clone(RandomListNode pHead) {
RandomListNode node = pHead;
while (node != null) {
// 复制一个当前结点,注意需要新建出结点
RandomListNode clone = new RandomListNode(node.label);
// 将复制结点插入当前结点后面
clone.next = node.next;
node.next = clone;
// 移动当前节点位置,继续循环
node = clone.next;
}
}
public void random(RandomListNode pHead) {
// 设置两个指向当前结点和复制结点的“指针”
RandomListNode node = pHead;
RandomListNode clone = null;
while (node != null) {
// if (node.next != null) {
clone = node.next;
// }
// 根据当前结点的random设置复制结点的random
if (node.random != null) {
clone.random = node.random.next;
}
node = clone.next;
}
}
// 抽出一个拆分链表的函数:将奇偶项分别拆开为两个链表
public RandomListNode copylist(RandomListNode pHead) {
RandomListNode plist = pHead;
// 记录复制链表的头结点,防止覆盖
RandomListNode clonehead = plist.next;
RandomListNode clonenode = plist.next;
plist.next = clonenode.next;
plist = plist.next;
while (plist != null) {
clonenode.next = plist.next;
clonenode = clonenode.next;
plist.next = clonenode.next;
plist = plist.next;
}
return clonehead;
}
public static void printList(RandomListNode head) {
while (head != null) {
System.out.print(head.label + "->");
head = head.next;
}
System.out.println("null");
}</span>