“节点”是ADT吗?如果是这样,它的界面是什么?

时间:2010-12-10 23:56:00

标签: c++ abstract-data-type

节点对于实现ADT很有用,但“节点”本身是ADT吗?如何实现“节点”?维基百科在节点上的(简短)文章中使用了一个没有方法的普通旧结构。我用google搜索节点试图找到关于它们的详尽文章,但大多数时候我发现文章讨论了用节点实现的更复杂的数据类型。

什么是节点?节点是否应该有链接到其他节点的方法,或者应该留给拥有节点的任何节点?一个节点应该是它自己的独立类吗?或者它是否足以将其包含为内部结构或内部类?他们是否过于笼统,甚至没有进行过这样的讨论?

7 个答案:

答案 0 :(得分:6)

节点是一个非常通用的术语。实质上,节点是图形中的顶点 - 或网络中的一个点。

关于数据结构,节点通常意味着单个基本数据单元(通常)连接到其他单元,形成更大的数据结构。一个简单的数据结构,演示这是一个链表。链表仅仅是一个节点链,其中每个节点(通过指针)链接到后续节点。结束节点有一个空指针。

节点可以形成更复杂的结构,例如图形,其中任何单个节点可以连接到任意数量的其他节点,或者树,其中每个节点具有两个或更多个子节点。请注意,由一个或多个连接节点组成的任何数据结构都是图形。 (链表和树也都是图表。)

在将“节点”的概念映射到类面向对象等概念方面,在C ++中,通常习惯使用数据结构类(有时称为容器),它将在内部完成所有关于个体的工作节点。例如,您可能有一个名为LinkedList的类。然后,LinkedList类将具有表示单个节点的内部定义(嵌套)类,例如LinkedList::Node

在一些更为粗略的实现中,您可能还会将Node本身视为访问数据结构的唯一方法。然后,您有一组在节点上运行的函数。但是,这在C程序中更常见。例如,您可能有struct LinkedListNode,然后将其传递给void LinkedListInsert(struct LinkedListNode* n, Object somethingToInsert);

等函数

在我看来,面向对象的方法更优越,因为它更好地隐藏了用户的实现细节。

答案 1 :(得分:1)

通常,您希望将节点操作留给ADT拥有它们的任何操作。例如,列表应该能够遍历自己的节点。它不需要节点具有该能力。

将节点视为ADT所拥有的简单数据位。

答案 2 :(得分:1)

ADT不是真正的类型。这就是为什么它被称为ADT。 “节点”是ADT吗?不是,IMO。它可以是一个的一部分,例如链表ADT。 '我刚创建的这个节点是否包含了东西'是ADT?绝对不!它充其量只是ADT实现的一个例子。

实际上只有一种情况可以表示ADT表示为代码,而这就是模板化的类。例如,来自C ++ STL的std :: list是一个实际的ADT,而不仅仅是一个实例的一个例子。另一方面,std::list<thingy>是ADT实例的一个示例。

有些人可能会说包含任何服从某些界面的列表也是ADT。我会温和地反对他们。这是一个ADT实现的例子,它可以包含各种必须遵守特定接口的对象。

可以对std :: list的“Concepts”的要求做出类似的论证。例如,类型T必须是可复制的。我会反驳说,这些只是ADT本身的要求,而以前的版本实际上需要特定的身份。概念比接口更高级。

真的,ADT非常类似于“模式”,除了ADT我们正在谈论算法,大O等...我们谈论抽象,重用等模式......在其他单词,模式是一种构建某种东西的方法,它可以解决特定类型的问题,并且可以扩展/重用。 ADT是一种构建可以通过算法操纵但不完全可扩展的对象的方法。

答案 3 :(得分:1)

在最严格的术语中,任何一种或多种原始类型的集合到某种类型的包中,通常具有对数据进行操作的成员函数,是一种抽象数据类型。

灰色区域主要来自您所使用的语言。例如,在Python中,一些编码器认为列表是基本类型,因此不是ADT。但在C ++中,STL List绝对是一个ADT。许多人会认为STL字符串是ADT,但在C#中它肯定是原始的。

更直接地回答你的问题:无论何时定义数据结构,无论是结构还是类,有或没有方法,它都必然是ADT,因为你将原始数据类型抽象为某种类型的构造有另一个目的。

答案 4 :(得分:0)

在ADT的上下文中,节点是您希望存储在数据结构中的数据,以及数据结构维护其完整性所需的一些管道元数据。不,节点不是ADT。良好的ADT库设计将避免继承,因为实际上并不需要它。

我建议你在编译器的标准C ++库中阅读std::map的代码,看看它是如何正确完成的。当然,您可能看不到ADT树而是红黑树,但节点结构应该相同。特别是,您可能会看到一个轻量级结构,它仍然是数据结构的私有结构,并且除了数据之外几乎没有。

答案 5 :(得分:0)

节点是实现更高级别的细节。节点不存在或独立运行 - 它们只存在,因为需要单独的生命周期和内存管理,而不是初始的链表,类。因此,它们并没有真正将自己定义为自己的类型,但如果它们的存在被有效地封装在用户之外,那么它们很快就存在而没有来自拥有类的封装。节点通常也不显示多态或其他OO行为。

一般来说,如果节点没有在该类的公共或受保护接口中出现,那么请不要打扰,只需将它们构成结构。

答案 6 :(得分:0)

您在问题中混合了三个主要是正交的概念:C ++,节点,ADT。

我认为尝试理清这些概念的交叉点可以说明一点是没有用的。

然而,事情可以说是例如C ++中的单链表节点。

#include <iostream>

template< class Payload >
struct Node
{
    Node*   next;
    Payload value;

    Node(): next( 0 ) {}
    Node( Payload const& v ): next( 0 ), value( v ) {}

    void linkInFrom( Node*& aNextPointer )
    {
        next = aNextPointer;
        aNextPointer = this;
    }

    static Node* unlinked( Node*& aNextPointer)
    {
        Node* const result  = aNextPointer;
        aNextPointer = result->next;
        return result;
    }
};

int main()
{
    using namespace std;
    typedef Node<int>   IntNode;

    IntNode*    pFirstNode  = 0;

    (new IntNode( 1 ))->linkInFrom( pFirstNode );
    (new IntNode( 2 ))->linkInFrom( pFirstNode );
    (new IntNode( 3 ))->linkInFrom( pFirstNode );

    for( IntNode const* p = pFirstNode;  p != 0;  p = p->next )
    {
        cout << p->value << endl;
    }

    while( pFirstNode != 0 )
    {
        delete IntNode::unlinked( pFirstNode );
    }
}

我早在八十年代初就在Pascal写过这些操作。

令我惊讶的是,他们知之甚少。 : - )

干杯&amp;第h。,