如图:每个节点有三个部分:value,next,random;除了与单链表相同的next域存放下一个节点的地址,random域可以存放任一个节点的地址(即可以指向任一个节点)或者为null;要拷贝一个这样结构的链表,应如何实现?
算法思路1:先复制原始链表的节点;然后在链表的头节点开始找每个节点的random,每次都要从头开始找,然后连接起来, 时间复杂度为O(n^2);
算法思路2:1、新建新节点,拷贝N的节点N',并将其插入到N的后面;
2、设置新节点的random域,N’的random域;
3、断开链表,将新旧链表断开。
代码取下:
public class CopyListNode{
static class Node<T>{
private T data;
private Node next;
private Node random;
public Node(){
next = null;
random = null;
}
public Node(T data){
this.data = data;
next = null;
random = null;
}
}
public Node copyList(Node head){
//创建新节点N',将N'连接在N后面
if(head == null){
return null;
}
Node p = head;
while(p != null){
Node q = new Node(p.data);
q.next = p.next;
q.random = null;
p.next = q;
p = q.next;
}
//设置N’的random
Node p1 = head;
while(p1 != null){
if(p1.random != null) {
p1.next.random = p1.random.next;
}
p1 = p1.next.next;
}
//拆分链表,奇数节点位置为原始链表,偶数节点位置为拷贝链表
Node p2 = head;
Node q2 = null;
Node s = null;
if(p2 != null){
s = q2 = p2.next;
p2.next = q2.next;
p2 = p2.next;
}
while(p2 != null){
s.next = p2.next;
s = s.next;
p2.next = s.next;
p2 = p2.next;
}
return q2;
}
public static void main(String[] args){
Node<Integer> head = new Node<>();
head.data = 1;
Node<Integer> n1 = new Node<>(2);
Node<Integer> n2 = new Node<>(3);
Node<Integer> n3 = new Node<>(4);
Node<Integer> n4 = new Node<>(5);
head.next = n1;
head.random = n2;
n1.next = n2;
n2.next = n3;
n3.next = n4;
n4.random = n1;
Node<Integer> copyhead = new Node<>();
CopyListNode n = new CopyListNode();
copyhead = n.copyList(head);
while(copyhead != null) {
System.out.println(copyhead.data);
copyhead = copyhead.next;
}
}
}
输出结果: