如何连接循环双向链表

时间:2014-09-25 08:58:22

标签: algorithm linked-list

考虑一下,我已经给出了两个圆形双向链表A和B的项。我想实现一个连接两个列表的函数。

这项任务很简单。但是,我想处理A和B是同一链表的成员的情况。在这种情况下,它什么也不做。是否可以在O(1)中实现它?我是否需要先检查A和B是否来自同一个列表?或者我可以以某种方式神奇地交换/混合指针?

IMO不可能,但我无法证明。

感谢

1 个答案:

答案 0 :(得分:1)

你可以。我自己很好奇,我用Java描绘了一个实现。假设链接列表如下

public class CLinkedList {

    class Node {
        Node prev, next;
        int val;

        public Node(int v) {
            val = v;
        }
    }

    Node s;

    public CLinkedList(Node node) {
        s = node;
    }

    void traverse() {
        if (s == null)
            return;

        Node n = s;
        do {
            System.out.println(n.val);
            n = n.next;
        } while (n != s);
    }
    ...
}

合并方法看起来像

void join(CLinkedList list) {
    Node prev = list.s.prev;
    Node sprev = s.prev;

    prev.next = s;
    sprev.next = list.s;
    s.prev = prev;
    list.s.prev = sprev; 
}

当列表不同时,它可以正常工作。

如果他们不是,那么所有这一切只是将原始列表拆分为两个完全有效的不同的链接列表。你应该做的只是再次加入他们。

编辑join方法加入(lol)两个列表(如果它们不同)或(与其名称相反)如果节点属于同一列表则拆分列表。因此,两次应用join确实没有效果。但您可以通过其他方式使用此属性。下面的方法工作正常:

public void merge(CLinkedList list) {
    CLinkedList nList = new CLinkedList(s.next);
    join(nList);
    nList.join(list);
    join(nList);
}

public static void main(String[] args) {
    CLinkedList list = new CLinkedList(new int[] {1,2,3});
    CLinkedList nlist = new CLinkedList(list.s.next);
    list.merge(nlist);
    list.traverse();
}

仍然是O(1):)保留小免责声明 - 不是最优质的代码,但你得到了图片。