繁体   English   中英

具有通用节点类型的双链表

[英]Doubly Linked List with generic node type

我需要一个可以在不同节点实现上使用的双向链表。 请注意,我不希望包含通用数据的节点,如DoublyLinkedNode<T> ,但像DoublyLinkedList<N extends DoublyLinkedNode<T>>

确切地说,在通常情况下,我将列表与标准节点一起使用,但在程序的其他部分中,我需要具有附加字段的节点。 所以我将通用节点实现为

public class DoublyLinkedNode<T> {
    DoublyLinkedNode<T> before, after;
    T value;
}

和特殊类型为

public class DoublyLinkedSpecialNode<T, S> extends DoublyLinkedNode<T> {
    S specialValue;
}

现在在我的DoublyLinkedList实现中,我希望能够在一个实例中处理这两种情况,因为所有代码基本上都会使用两个实现明显相同的指针。

这给出了一些要求:

1)当我使用特殊节点时,我希望能够将其作为DoublyLinkedSpecialNode类型返回,以便能够访问其他字段。

2)该列表必须使用DoublyLinkedNode类型来访问节点的指针。

3)列表将指向的节点分配给其他节点,例如head = node.after; ,因此特殊节点中指针的类型必须与列表中的类型相同。

扩展列表毫无意义,因为我无法更改方法的返回类型。 因此,我尝试了两个想法,但没有成功:

已经提到的解决方案:从DLN扩展的通用节点类型

列表看起来像这样:

public class DoublyLinkedList<T, N extends DoublyLinkedNode<T>> {
    N head, tail;
    N tail() {
        return tail; // OK
    }
    void remove(N node) {
        if (head == node) {
            head = node.after; // Type error
        }
...

此解决方案与要求3)冲突,因为在列表中类型是从DLN扩展的N,但是在节点实现N中,指针是基类/接口DLN的类型(理论上,指针类型可以更通用)比N)。

基本DLN而非通用

在这种情况下,列表在基类节点上工作,并且由于多态性而接受子类:

public class DoublyLinkedList<T> {
    DoublyLinkedNode<T> head, tail;
    DoublyLinkedNode<T> tail() {
        return tail; 
    }
    void remove(DoublyLinkedNode<T> node) {
        if (head == node) {
            head = node.after; // OK
        }
...

但是tail()只能返回一般类型的节点,与1)冲突。 我宁愿不使用强制转换,因为我认为这是不好的做法(?),但也因为实现对性能至关重要。 当然有更好的方法吗?

我找到了另一种解决方案,它是好的,不是很高效,但比上一个解决方案更优雅。

这个想法只是使用一种类型的节点,并将不同的内容包装在一个通用的容器中。 DLN代码如下所示:

public class DoublyLinkedNode<C> {
    DoublyLinkedNode<C> before, after;
    C content;

    public static class ValueContent<T> {
        T value;
    }

    public static class ValueSpecialContent<T, S> extends ValueContent<T> {
        S specialValue;
    }
}

然后列表实现看起来像这样:

public class DoublyLinkedList<C> {
    DoublyLinkedNode<C> head, tail;

    public DoublyLinkedNode<C> head() {
        return head;
    }

    void remove(DoublyLinkedNode<C> node) {
        if (head == node) {
            head = node.after;
...

我可以从调用类访问特殊字段,如下所示:

DoublyLinkedList<SpecialContent<SpecialType>> list;
SpecialType s = list.head().content.specialValue;

有一些开销,因为每个节点都必须实例化该容器类,但是我认为它仍然比强制转换更好。 我必须检查性能影响。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM