`

java-拷贝特殊链表:有一个特殊的链表,其中每个节点不但有指向下一个节点的指针pNext,还有一个指向链表中任意节点的指针pRand,如何拷贝这个特殊链表?

 
阅读更多
public class CopySpecialLinkedList {

	/**
	 * 题目:有一个特殊的链表,其中每个节点不但有指向下一个节点的指针pNext,还有一个指向链表中任意节点的指针pRand,如何拷贝这个特殊链表?
拷贝pNext指针非常容易,所以题目的难点是如何拷贝pRand指针。
假设原来链表为A1 -> A2 ->... -> An,新拷贝链表是B1 -> B2 ->...-> Bn。
为了能够快速的找到pRand指向的节点,并把对应的关系拷贝到B中。我们可以将两个链表合并成
A1 -> B1 -> A2 -> B2 -> ... -> An -> Bn。
从A1节点出发,很容易找到A1的pRand指向的节点Ax,然后也就找到了Bx,将B1的pRand指向Bx也就完成了B1节点pRand的拷贝。依次类推。
当所有节点的pRand都拷贝完成后,再将合并链表分成两个链表就可以了。
	 */
	public static void main(String[] args) {
		int[] data = { 1, 2, 3, 4, 5 };
		SpecialLinkList sList = new SpecialLinkList();
		SpecialLinkList.Node source = sList.create(data);
		sList.pRand(0, 4);//add 'pRand'
		sList.pRand(1, 3);
		sList.pRand(2, 0);
		sList.pRand(3, 2);
		sList.pRand(4, 1);
		sList.print(source);
		SpecialLinkList.Node dest = sList.copyPNext(source);
		sList.copyPRand(dest, source);
		sList.print(dest);
	}

}

class SpecialLinkList {

	private Node head;

	class Node {
		int val;
		Node pNext;
		Node pRand;

		Node(int val) {
			this.val = val;
		}
	}

	public Node copyPNext(Node source) {
		Node pre = null;// previous node
		Node dest = null;// destination node
		while (source != null) {
			int val = source.val;
			Node cur = new Node(val);// current node
			if (pre == null) {
				pre = cur;
				dest = pre;
			} else {
				pre.pNext = cur;
				pre = cur;
			}
			source = source.pNext;
		}
		return dest;
	}

	public Node copyPRand(Node dest, Node source) {
		Node a = source;
		Node b = dest;
		// create a1-b1-a2-b2...
		while (a != null && b != null) {
			Node tmp = a.pNext;
			a.pNext = b;
			a = b;
			b = tmp;
		}
		// copy pRand
		a = source;
		b = a.pNext;
		while (a.pNext != null) {
			Node tmp = a.pNext.pNext;
			b.pRand = a.pRand.pNext;
			if (tmp == null) {
				break;
			}
			a = tmp;
			b = a.pNext;
		}
		// split a1-b1-a2-b2... to a1-a2...,b1-b2....
		a = source;
		b = source.pNext;
		dest = b;
		while (a.pNext.pNext != null) {
			Node tmp = a.pNext.pNext;
			a.pNext = tmp;
			a = tmp;

			tmp = b.pNext.pNext;
			b.pNext = tmp;
			b = tmp;
		}
		a.pNext = null;
		b.pNext = null;
		return dest;
	}

	// create a linked list.Insert from tail.
	public Node create(int[] data) {
		if (data == null || data.length == 0) {
			return null;
		}
		Node tail = null;
		for (int len = data.length, i = len - 1; i >= 0; i--) {
			Node tmp = new Node(data[i]);
			tmp.pNext = tail;
			tail = tmp;
		}
		head = tail;
		return head;
	}

	// create 'pRand' between posX and posY
	public void pRand(int posX, int posY) {
		if (posX < 0 || posY < 0) {
			return;
		}
		Node nodeX = getNodeAt(posX);
		Node nodeY = getNodeAt(posY);
		if (nodeX != null && nodeY != null) {
			nodeX.pRand = nodeY;
		}
	}

	// get the node at the specific position.The position starts from 0.
	public Node getNodeAt(int pos) {
		if (pos < 0) {
			return null;
		}
		if (head == null) {
			return null;
		}
		Node node = head;
		while (node != null && pos > 0) {
			node = node.pNext;
			pos--;
		}
		return node;
	}
	//print the special linked list,like 1(5)-2(4)-3(1)-4(3)-5(2).'5' is the pRand of '1',and so on.
	public void print(Node node) {
		while (node != null) {
			System.out.print(node.val + "");
			if (node.pRand != null) {
				System.out.print("(" + node.pRand.val + ")-");
			}
			node = node.pNext;
		}
		System.out.println();
	}

}

0
0
分享到:
评论
1 楼 LoadingTerry 2012-10-07  
朋友 你好!我想和你交流java技术,方便留个联系方式吗?

相关推荐

    拷贝具有随机指针节点的链表,

    在本问题中,我们关注的是一个特殊的链表,其中包含了一个额外的随机指针(random pointer),这个指针可以指向链表中的任意节点,而不仅限于下一个节点。这个数据结构在某些算法问题和复杂数据模型中非常有用。 ...

    MLDN魔乐JAVA_13链表.MLDN魔乐JAVA_13链表.rar

    - 双链表:每个节点有两个指针,分别指向前一个节点和后一个节点,方便双向遍历。 - 循环链表:最后一个节点的指针不指向null,而是指向链表的第一个节点,形成一个循环。 - 带头节点的链表:链表的第一个节点是头...

    SPT-02-链表.pdf

    - 双链表:每个节点有两个指针,一个指向前一个节点,一个指向后一个节点,便于双向遍历。 - 循环链表:最后一个节点的指针指向头节点,形成一个循环。 - 带头节点的链表:链表额外添加一个头节点,方便操作。 2...

    插入、删除、修改指向下一节点和下下一节点链表

    操作一个链表,链表中的节点有两个指针,一个指向下一个节点, 一个指向下下一个节点,如果下一个节点或者下下一个节点为空,则为null。 操作为插入,删除,修改。 博客:...

    java链表实现

    链表由一系列节点组成,每个节点包含数据和指向下一个节点的引用。本篇将深入探讨如何在Java中实现单链表,包括其基本操作、优势以及常见应用。 1. **链表的基本概念** - 链表是一种线性数据结构,其中的元素不是...

    链表的基本操作,插入删除查找等

    2. **双向链表**:每个节点有两个指针,一个指向前一个节点,另一个指向后一个节点。双向链表支持双向遍历,因此在某些操作中更为灵活。 3. **循环链表**:最后一个节点的指针指向链表的第一个节点,形成一个循环。...

    算法设计-实验五-链表.docx

    与数组不同,链表的元素不需要连续的内存空间,每个元素(称为节点)包含数据和指向下一个节点的引用。本资源专注于Python中链表的实现,通过实验五的描述,我们可以学习以下关键知识点: 1. **链表的基本概念**: ...

    c++写的链表综合算法设计

    - 双链表:每个节点有两个指针,一个指向前一个节点,一个指向后一个节点。 - 循环链表:链表的最后一个节点的指针指向头节点,形成一个循环。 3. **链表的操作**: - 创建链表:初始化头节点,然后根据需求动态...

    链表面试题_链表_面试题_cow3cm_数据结构_

    - 双链表:每个节点有两个指针,一个指向前一个节点,一个指向后一个节点。 - 循环链表:最后一个节点的指针指向链表的第一个节点,形成一个循环。 - 带头节点的链表:链表的开头有一个特殊的节点,称为头节点,...

    java 数据结构 链表

    - 单向链表的节点定义:通常会有一个类表示链表节点,例如`Node`,包含一个数据字段和一个指向下一个节点的引用字段。 - 插入操作:在链表的头部或尾部插入新节点相对简单,只需改变相应节点的引用即可。 - 删除...

    链表相关的算法程序

    链表是由一系列节点构成的数据结构,每个节点包含数据部分和指向下一个节点的指针。不同于数组,链表的元素在内存中不是连续存储的。这种非连续性使得链表在插入和删除操作上通常比数组更高效,但随机访问则相对较慢...

    整数链表

    双向链表每个节点还包含一个指向前一个节点的指针,而循环链表则将最后一个节点的指针链接回链表的第一个节点。 ### 3. 链表类的设计 在实现整数链表时,首先需要创建一个类,比如命名为`IntegerLinkedList`。这个...

    算法-理论基础- 线性表- 双向链表(包含源程序).rar

    双向链表与单链表相比,具有更多的灵活性,因为它的每个节点不仅包含了指向下一个节点的指针,还包含了指向前一个节点的指针。 双向链表的基本结构包括节点和指针。每个节点包含三部分:数据域,用于存储元素;前驱...

    计算机等级考试二级C语言链表复习资料

    - 双链表:每个节点有两个指针,一个指向前驱节点,一个指向后继节点,便于双向遍历。 - 循环链表:链表的最后一个节点的指针指向头节点,形成循环结构。 - 带头链表:链表的第一个节点是专门的头节点,不存储...

    数据结构 链表

    - 双链表:每个节点有两个指针,一个指向前一个节点,一个指向后一个节点,使得双向遍历成为可能。 - 循环链表:最后一个节点的指针域指向链表的第一个节点,形成一个循环。 - 带头节点的链表:在链表的开始处...

    c 数据结构 链表源码

    单向链表的每个节点只能向前指向下一个节点,而双向链表的节点则同时拥有前向和后向指针。循环链表则在链表的最后一个节点指向头节点,形成一个闭合的环状结构。 1. 单向链表: - 创建链表:通过动态内存分配创建...

    单链表 双链表 循环链表 源代码

    - 双链表与单链表类似,但每个节点除了有一个指向后继节点的指针外,还有一个指向前驱节点的指针。 - 特点:双链表支持双向遍历,插入和删除操作比单链表更高效,因为可以向前或向后移动。 - C语言实现:双链表的...

    java 单链表和双向链表的实现

    而双向链表则更进一步,每个节点不仅有指向下一个节点的指针,还有一个指向前一个节点的指针。这种额外的指针使得双向链表在某些操作上比单链表更灵活,但也增加了存储空间的需求。 **单链表的实现:** 在Java中,...

    c\c++链表实例

    - 双向链表的每个节点有指向前一个节点和后一个节点的两个指针,提供更灵活的遍历方向。 - 在双向链表中进行插入和删除操作,需要同时调整前后节点的指针。 4. 链表的实现: - 创建链表:通常从空链表开始,逐步...

Global site tag (gtag.js) - Google Analytics